2018牛客多校第四場 A Ternary String
阿新 • • 發佈:2019-01-25
設dp[i]為刪掉原本的第i位需要經過多少天,然後可以根據規則發現一些規律,如果第i位是2的話,dp[i]=6*2^dp[i-1]-3,如果是第1位的話就是dp[i]=2^dp[i-1]+2,0:dp[i]=dp[i-1]+1,然而dp陣列是非常大的,需要對mod進行取模,但是呼叫之前的dp[i-1]已經是取模過得,那麼dp[i-1]的冪次必須是要對phi(mod)取模,而dp[i-1]又是由dp[i-2]轉移過來的,那麼在計算dp[i-1]的時候2^dp[i-2]這一項,dp[i-2]要對phi(phi(mod))取模,預處理出對於每個mod的phi[mod],就可以nlogn的遞迴呼叫了。然而考場上並沒有想到,而是直接對每一個phi[p]都遞推一遍,n*30*log(1e9),無盡的TLE,最後向aols求取了一波人生的經驗,先預處理出一個數組mi[j][i],代表2^i對phi[j]取模的結果,在遞推的時候如果2的冪小於maxi,那麼直接從數組裡取得,不進行快速冪。於是我發現maxi必須開1e6,再大1e5超空間,再小2*1e5超時,最後3579ms卡過去的。。。不過如果能想到遞迴呼叫,就140+ms能過了。
#include<bits/stdc++.h> #define X first #define Y second #define pb push_back #define mk make_pair #define rep(i,l,r) for(int i=l;i<=r;++i) using namespace std; typedef long long LL; const int maxn=1e6,mod=1e9+7,M=30,maxl=1e5+5; int n,m; int f[maxl][M]; int mi[M][maxn]; char s[maxn]; int a[M]; inline int Pow(int a,int b,int mod) { int ans=1; while(b) { if(b&1)ans=((LL)ans*a)%mod; a=((LL)a*a)%mod; b>>=1; } return ans; } inline int calc(int t,int tt,int j) { int mod=a[j]; if(mod==1)return 0; if(t==1ll)return 2ll; if(tt<maxn) return (3ll*(1ll*mi[j][tt]-1ll+mod)%mod-t+mod)%mod; else return (3ll*(1ll*Pow(2ll,tt,mod)-1ll+mod)%mod-t+mod)%mod; } int main() { a[1]=1; a[2]=2; a[3]=4; a[4]=8; a[5]=16; a[6]=32; a[7]=64; a[8]=128; a[9]=256; a[10]=512; a[11]=1024; a[12]=2048; a[13]=4096; a[14]=8192; a[15]=16384; a[16]=32768; a[17]=65536; a[18]=131072; a[19]=262144; a[20]=524288; a[21]=1048576; a[22]=2097152; a[23]=5242880; a[24]=19660800; a[25]=79872000; a[26]=243900800; a[27]=500000002; a[28]=1000000006; a[29]=1000000007; for(int i=2;i<M;i++) { mi[i][0]=1; for(int j=1;j<maxn;j++) mi[i][j]=(mi[i][j-1]<<1)%a[i]; } int t; scanf("%d",&t); while(t--) { scanf("%s",s+1); n=strlen(s+1); //memset(f,0,sizeof(f)); for(register int i=2;i<M;++i) f[1][i]=(s[1]-'0'+1)%a[i]; for(register int i=2;i<=n;++i) { if(s[i]=='0') for(register int j=2;j<M;++j) f[i][j]=(f[i-1][j]+1)%a[j]; else if(s[i]=='1') for(register int j=2;j<M;++j) f[i][j]=((f[i-1][j]<<1)+2)%a[j]; else for(register int j=2;j<M;++j) f[i][j]=(f[i-1][j]+calc(f[i-1][j]+1,f[i-1][j-1]+1,j)+1)%a[j]; } printf("%d\n",f[n][29]); } return 0; } /* 3 012 22 */
#include<bits/stdc++.h> #define X first #define Y second #define pb push_back #define mk make_pair #define rep(i,l,r) for(int i=l;i<=r;++i) using namespace std; typedef long long LL; const int maxn=1e5+5,mod=1e9+7,M=30; int n,m; char s[maxn]; int a[M]; inline int Pow(LL a,LL b,int mod) { int ans=1; while(b) { if(b&1)ans=((LL)ans*a)%mod; a=(a*a)%mod; b>>=1; } return (int)ans; } inline LL calc(int t,int mod) { if(t==0)return 0; if(mod==1)return 0; if(s[t]=='0')return (calc(t-1,mod)+1)%a[mod]; else if(s[t]=='1')return (calc(t-1,mod)*2+2)%a[mod]; else return (3ll*(Pow(2ll,calc(t-1,mod-1)+1,a[mod])-1ll)%a[mod]+a[mod])%a[mod]; } int main() { a[1]=1; a[2]=2; a[3]=4; a[4]=8; a[5]=16; a[6]=32; a[7]=64; a[8]=128; a[9]=256; a[10]=512; a[11]=1024; a[12]=2048; a[13]=4096; a[14]=8192; a[15]=16384; a[16]=32768; a[17]=65536; a[18]=131072; a[19]=262144; a[20]=524288; a[21]=1048576; a[22]=2097152; a[23]=5242880; a[24]=19660800; a[25]=79872000; a[26]=243900800; a[27]=500000002; a[28]=1000000006; a[29]=1000000007; int t; scanf("%d",&t); while(t--) { scanf("%s",s+1); n=strlen(s+1); printf("%lld\n",calc(n,29)); } return 0; } /* 3 012 22 000 */