牛客網暑期ACM多校訓練營(第四場)A.Ternary String(擴充套件尤拉定理)
阿新 • • 發佈:2018-11-10
題意
每秒鐘2後面加一個1,1後面加1個0,然後刪除第一個字元,問需要多少秒才能刪完
題解
可以發現:0會使答案加1,1會使答案T*2+2,2會使答案T變成(2^(T+1)-1)*3,所以一邊計算即可,但是由於要取模,所以需要擴充套件尤拉定理,證明轉載自http://blog.csdn.net/synapse7/article/details/19610361,我也就不在這說了,自己也不太懂;考慮到可能會TLE,所以需要提前儲存需要用到的尤拉值,然後逆著做一遍,參考著做題
擴充套件尤拉定理
AC程式碼
#include<bits/stdc++.h> #define N 2000005 #define P pair<int,int> using namespace std; typedef long long ll; const int M=1e9+7; const int MM=1e9+6; const int inf=1e9+7; ll Mod(ll x,ll y){ return x < y ? x : x % y + y; } long long euler(long long n) { ll m = sqrt(n+0.5); ll ans = n; for(int i=2; i<=m; ++i) if(n%i == 0) { ans = ans/i * (i-1); while(n%i == 0) n /= i; } if(n > 1) ans = ans/n * (n-1); return ans; } ll quick(ll a,ll b,int mod) { ll c=1; while(b){ if(b&1)c=Mod(c*a,mod); a=Mod(a*a,mod); b>>=1; } return c; } char s[N]; vector<int>phi; ll solve(int n,int m,int d) { if(n<=0)return 0; if(s[n]=='2'){ if(d>=phi.size())d=phi.size()-1; ll t=solve(n-1,phi[d],d+1); t=quick(2,t+1,m); return Mod(3*(t-1),m); } if(s[n]=='0')return Mod(solve(n-1,m,d)+1,m); return Mod(solve(n-1,m,d)*2+2,m); } int main() { int t; int k=M; while(k!=1){ k=euler(k); phi.push_back(k); } for(scanf("%d",&t);t;t--) { scanf("%s",s+1); int n=strlen(s+1); printf("%lld\n",solve(n,M,0)%M); } return 0; } /* 3 000 012 22 */