F. Kirei and the Linear Function(思维 + 哈希 + 预处理)
生活随笔
收集整理的這篇文章主要介紹了
F. Kirei and the Linear Function(思维 + 哈希 + 预处理)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
F. Kirei and the Linear Function
思維 + 哈希 + 預處理
分析
觀察到每組數據的w是確定的,所以我們可以先對s的每個長度為w的子串[l,l+w-1]都給切片一下;
把他們的值%9算出來,用map存相同值的切片的左端點的集合;
那么問題來了,怎么快速算出每一段切片的十進制下%9的值???
由于字符串全都是0~9,且是%9,所以非常的特殊;
比如:321 = (31010)%9 + (210)%9 + 1%9 = (311) + (21) + 1;
所以可以發現每個切片的值就是切片中每個字符的值之和%9;
所以這里我們就可以用一個前綴和來記錄處理一下每一個切片,就能快速算出來了;
當然更一般的寫法就是直接字符串hash就行了,套個板子就行
然后對于每個詢問,要求(v(l1) * v + v(l2)) % 9 = k; 的最小l1,l2;
所以我們可以直接枚舉v(l1) (0~8);
那么v(l2) = (k - (v(l1) * v % 9) + 9) % 9;
然后判斷一下,更新最小下標就行
代碼
#include<iostream> #include<queue> #include<cstring> #include<vector> #include<stdio.h> #include<map> #include<algorithm> #include<deque> #include<stack> #include<set> #include <random> #include<bitset> // #include <unordered_map> #include<math.h> #include<string.h> #define IOS ios::sync_with_stdio(false),cin.tie(0); using namespace std;#define pb push_back #define coutl cout<<"------------"<<endl; #define fi first #define se second#define ire(x) scanf("%d",&x) #define iire(a,b) scanf("%d %d",&a,&b) #define lre(x) scanf("%lld",&x) #define llre(a,b) scanf("%lld %lld",&a,&b) #define dre(x) scanf("%lf",&x) #define ddre(a,b) scanf("%lf %lf",&a,&b) #define rep(i,a,b) for(int i=a;i<=b;i++) #define endl "\n" #define PI acos(-1.0) //#define int long long // #define double long double // typedef __int128 ll; typedef long long ll; typedef unsigned long long ull;typedef pair<int, int> PII; typedef pair<double, int> PDI; typedef pair<ll, ll> PLL; typedef pair<double, double> PDD; typedef pair<double, pair<int, double> > PDID; typedef pair<char, char> PCC; typedef pair<char, int> PCI; typedef pair<char, pair<int, int> > PCII; typedef pair<int, pair<int, int> > PIII; typedef pair<int, pair<int, pair<int, int> > > PIIII; typedef pair<ll, pair<int, int> > PLII;const int maxn = 2e5 + 7; const int N = 5e5 + 7; const int M = 5e5 + 7; const int mod = 131; const int inv = mod - mod/2; const int inf = 0x3f3f3f3f; const ll INF = 0x3f3f3f3f3f3f3f3f; const double pi = acos(-1); const double eps = 1e-8;ll gcd(ll a,ll b) {return b==0 ? a : gcd(b,a%b);} ll lcm(ll a,ll b) {return a*b / gcd(a,b);} ll qmi(ll a,ll b,ll p) {ll ans = 1; while(b) { if(b & 1) ans = ans * a % p; a = a * a % p; b >>= 1; } return ans;} int lowbit(int x) {return x & (-x);}ll sum[maxn]; //前綴和處理切片void solve() { string s;cin>>s;s = ' ' + s;//前綴和for(int i=1;i<s.size();i++) sum[i] = sum[i-1] + (s[i] - '0');int w,m;cin>>w>>m;//求切片map<int,vector<int>> mp; //存不同切片值的左端點下標for(int i=1;i+w-1<s.size();i++){int j = i + w - 1;int num = (sum[j] - sum[i-1]) % 9;mp[num].pb(i);}while(m--){int l,r,k;cin>>l>>r>>k;int num = (sum[r] - sum[l-1]) % 9; //v的值// cout<<num<<'\n';int ans1 = inf;int ans2 = inf;for(int v1=0;v1<=8;v1++) //枚舉v1{if(mp[v1].size() == 0) continue;int v2 = (k - (v1 * num % 9) + 9) % 9;if(mp[v2].size() == 0) continue; //當前v2的沒有切片if(v1 == v2 && mp[v1].size() == 1) continue; //l1 = l2,不滿足if(v1 != v2) //v1 v2值不相等,則都取最小的下標更新{if(ans1 > mp[v1][0]){ans1 = mp[v1][0];ans2 = mp[v2][0];}else if(ans1 == mp[v1][0] && ans2 > mp[v2][0])ans2 = mp[v2][0];}else //v1 v2值相等,一樣的{if(ans1 > mp[v1][0]){ans1 = mp[v1][0];ans2 = mp[v1][1];}else if(ans1 == mp[v1][0] && ans2 > mp[v1][1])ans2 = mp[v1][1];}}if(ans1 == inf || ans2 == inf) ans1 = -1, ans2 = -1;cout<<ans1<<' '<<ans2<<'\n';} }int main() {IOS;int t;cin>>t; // t = 1;while(t--){solve();}return 0; }總結
以上是生活随笔為你收集整理的F. Kirei and the Linear Function(思维 + 哈希 + 预处理)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java中的mvc和三层结构究竟是什么关
- 下一篇: RDD 持久化