题意转换:构造一个长度为n的只含0、1的序列,使得序列中任意的为质数长度的子串中0的数量>=1的数量,求构造方案数%(1e9+7)。
思路:打表找规律发现是fib数列,a(n)=a(n-1)+a(n-3),矩阵快速幂
构造矩阵
⎡⎣⎢a(n)a(n−1)a(n−2)⎤⎦⎥=⎡⎣⎢110001100⎤⎦⎥∗⎡⎣⎢a(n−1)a(n−2)a(n−3)⎤⎦⎥
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define sa(x) scanf("%d",&x)
typedef long long ll;
const ll mod=1e9+7;
struct Matrix {
ll mat[4][4];
Matrix() {
memset(mat,0,sizeof mat);
}
};
Matrix multi(Matrix a,Matrix b) {
Matrix c;
for(int i=1;i<=3;++i) {
for(int j=1;j<=3;++j) {
for(int k=1;k<=3;++k) {
c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j]%mod)%mod;
}
}
}
return c;
}
ll mat_pow(ll x) {
Matrix ans;
ans.mat[1][1]=ans.mat[2][2]=ans.mat[3][3]=1;
Matrix m;
m.mat[1][1]=m.mat[1][3]=m.mat[2][1]=m.mat[3][2]=1;
while(x) {
if(x&1) ans=multi(ans,m);
m=multi(m,m);
x>>=1;
}
return ((ans.mat[1][1]*6ll+ans.mat[1][2]*4ll)%mod+ans.mat[1][3]*3ll)%mod;
}
int main() {
int T;
sa(T);
ll n;
while(T--) {
scanf("%I64d",&n);
if(n==2) puts("3");
else if(n==3) puts("4");
else if(n==4) puts("6");
else printf("%I64d\n",mat_pow(n-4)%mod);
}
return 0;
}
奇怪的是,一样的代码在vj上343ms A了,在hdu上T了好几发最后998ms卡过
打表程序
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define sa(x) scanf("%d",&x)
const int N=105;
int p[N],is_p[N],sum[N],a[N];
int ans=0,n;
int pcnt=0;
void init() {
for(int i=2;i<N;++i) {
if(!is_p[i]) {
p[++pcnt]=i;
for(int j=2*i;j<N;++j) is_p[j]=1;
}
}
}
bool judge() {
sum[0]=0;
for(int i=1;i<=n;++i) sum[i]=sum[i-1]+a[i];
for(int k=1;k<=pcnt&&p[k]<=n;++k) {
int len=p[k];
for(int i=1;i+len-1<=n;++i) {
int j=i+len-1;
int a1=sum[j]-sum[i-1];
int a0=len-a1;
if(a1<a0) return false;
}
}
return true;
}
void dfs(int pos) {
if(pos==n+1) {
if(judge()) ++ans;
return ;
}
a[pos]=0;
dfs(pos+1);
a[pos]=1;
dfs(pos+1);
}
int main() {
freopen("out.txt","w",stdout);
init();
for(int i=2;i<20;++i) {
n=i;
ans=0;
dfs(1);
pr(ans);
}
fclose(stdout);
return 0;
}