题目地址:点这里
额,思考的方式还是在纸上,举几个简单的例子。找找规律。
首先,只有一个循环节的时候,就是sigma pow(2,p[i]) 其中p[i] 为s[p[i]] =='0'||'5';
然后有k个循环节的时候,找到了递推方程。f[n]=f[n-1]+2^(Length*(n-1))*T;
其中T是一个循环节对应的方法数。
f[n]可以理解为,仅使用前n个循环节对应的方法数,那么对最后一个循环节,要么不用(f[n-1] ) ,要么用,前面n-1 循环节,对应(n-1)*Length 这么多元素,都可以取或者不取。
于是就是一个等比数列求和。
但是不能再分母上取模。
所以设计了一个矩阵,使用矩阵快速幂来解决。
注意:凡是两个int相乘的地方就要取mod。
代码:
#include<iostream>
using namespace std;
typedef long long inta;
const int mod=1000000007;
int p[100005];
inta quick_mod(inta a,int n)
{
inta ans=1;
while(n>0)
{
if(n&1)
{
ans=(ans*a)%mod;
}
a=(a*a)%mod;
n>>=1;
}
return ans;
}
struct Matrix {
inta p[2][2];
Matrix()
{
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
p[i][j]=(i==j)?1:0;
}
};
Matrix multi(Matrix A,Matrix B)
{
Matrix ans;
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
{
inta sum=0;
for(int k=0;k<2;k++)
{
sum=(sum+(A.p[i][k]*B.p[k][j])%mod)%mod;
}
ans.p[i][j]=sum;
}
return ans;
}
Matrix quick_mod(Matrix A,int n)
{
Matrix ans;
while(n)
{
if(n&1)
{
ans=multi(ans, A);
}
A=multi(A, A);
n>>=1;
}
return ans;
}
int main()
{
string s;
cin>>s;
inta L=s.length();
inta Base=quick_mod(2,L);
int k;
cin>>k;
inta T=0;
int c=0;
for(int i=0;i<s.length();i++)
{
if(s[i]=='0'||s[i]=='5') p[c++]=i;
}
for(int i=0;i<c;i++)
{
T=(T+quick_mod(2, p[i]))%mod;
}
Matrix A;
A.p[0][0]=1;
A.p[0][1]=0;
A.p[1][0]=1;
A.p[1][1]=Base;
A=quick_mod(A, k-1);
inta TB=(T*Base)%mod;
cout<<((T*A.p[0][0])%mod+(TB*A.p[1][0])%mod)%mod<<endl;
}
其实本题的答案就是T*(2^0+2^(L)+2^(2L)+...+2^(k-1)L)
就是枚举最后一位出现在第几个循环节,然后前面的长度任取。
等比数列求和的类似于快速幂的写法
改了一下,简洁很多。
代码:
#include<iostream>
using namespace std;
typedef long long inta;
const int mod=1000000007;
int p[100005];
inta quick_mod(inta a,int n)
{
inta ans=1;
while(n>0)
{
if(n&1)
{
ans=(ans*a)%mod;
}
a=(a*a)%mod;
n>>=1;
}
return ans;
}
inta calc(inta A,int n) // 等比数列求和
{
if(n==0) return 1;
if(n==1) return (1+A)%mod;
if(n%2==0)
{
inta x=calc(A,n/2);
inta d=quick_mod(A, n/2);
return ((d*(x-1))%mod+x)%mod;
}
else
{
inta x=calc(A,(n-1)/2);
inta d=quick_mod(A, (n+1)/2);
return ((d*x)%mod+x)%mod;
}
}
int main()
{
string s;
cin>>s;
inta L=s.length();
inta Base=quick_mod(2,L);
int k;
cin>>k;
inta T=0;
int c=0;
for(int i=0;i<s.length();i++)
{
if(s[i]=='0'||s[i]=='5') p[c++]=i;
}
for(int i=0;i<c;i++)
{
T=(T+quick_mod(2, p[i]))%mod;
}
cout<<(calc(Base,k-1)*T)%mod<<endl;
return 0;
}