设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
*/