设前面经过t秒才到这个s[i].
那么删这个数(和他的生产物)有这个规律
0: t+1
1: 2*(t+1)
2: 3*(2^(t+1)-1)
虽然找到了规律,可以用递推的方法求出答案。但是答案一下成为幂,但是一下又要对1e9+7取模。所以只能用欧拉函数降幂做。
我们可以利用欧拉函数phi()的性质。
对于a,c互质成立。
对于a,c不互质的情况。用广义欧拉定理:
对于递归求解的思路,可以参考Bzoj 3884: 上帝与集合的正确用法
对于细节,看代码注释
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <map>
using namespace std;
#define LL long long
const LL maxn = 1e5+55;
char s[maxn];
map<LL,LL> mp;
LL phi(LL x)//算欧拉,并且记忆
{
if(mp[x]) return mp[x];
LL temp=x;
LL ans=x;
if(x==1) return mp[1]=1;
for(LL i=2;i*i<=x;i++){
if(x%i==0){
ans=ans/i*(i-1);
while(x%i==0) x/=i;
}
}
if(x>1) ans=ans/x*(x-1);
return mp[temp]=ans;
}
LL qkm(LL base,LL mi,LL mod)
{
while(mi<0) cout<<1;
LL ans=1;
while(mi){
if(mi&1) ans=ans*base%mod;
base=base*base%mod;
mi>>=1;
}
return ans;
}
LL solve(LL x,LL mod)
{
if(x==0||mod==1) return 0;
if(s[x]=='0'){
return (1LL+solve(x-1,mod)+mod)%mod;
}else if(s[x]=='1'){
return (2*(solve(x-1,mod)+1)+mod)%mod;
}else{
LL ph=phi(mod);
LL t=(solve(x-1,ph))%ph;//对于solve(x-1,ph)是对ph取模的,肯定比ph小,所以用第一个广义欧拉降幂。
return (qkm(2,t,mod)*6%mod-3+mod*10)%mod;//注意最后只加一个mod还是可能为负数,干脆mod*10
}
}
int main()
{
LL T;
scanf("%lld",&T);
while(T--){
scanf("%s",s+1);
printf("%lld\n",solve(strlen(s+1),1e9+7));
}
}