题意:求由1到k之间的数字组成的,满足如果ai=aj,则i-j>=ai的序列个数
一脸懵逼在比赛中想不出AC方法,50分做法:考虑状压,因为新的一位能放哪些数字只和最后m-1位有关,又因为k<=7,于是考虑状压.
在50分数据也就是k=5时刚好能跑出来
时间复杂度O(n*k^k),大数据直接爆炸= =毕竟太弱
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<bitset> #define LL long long #define fo(i,a,b) for(int i=a;i<=b;i++) using namespace std; inline LL read() { LL d=0,f=1;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();} return d*f; } #define N 10005 #define M 8 #define inf 910109 int f[2][10000]; struct S { int x,y; }s[1000]; int n,m,num=0,ma=0; int po8[10]; int c[9]; void dfs(int k) { if(k>m) { int x=0,y=0; fo(i,1,m) { if(i!=m)x+=c[i]*po8[i-1]; if(i!=1)y+=c[i]*po8[i-2]; } // cout<<num+1<<endl; // fo(i,1,m)cout<<c[i]<<' ';cout<<endl; s[++num].x=x;s[num].y=y; // f[1-m%2][x]++; ma=max(ma,max(x,y)); return; } bitset<10>a;a.reset();c[k]=1;dfs(k+1);c[k]=0; for(int i=k-1,j=2;j<=m;i--,j++) { if(i>0)a[c[i]]=1; if(a[j]==0) { c[k]=j; dfs(k+1); c[k]=0; } } } void prework() { po8[0]=1; fo(i,1,7)po8[i]=po8[i-1]*8; memset(c,0,sizeof(c)); memset(f,0,sizeof(f)); dfs(1); fo(i,1,num)f[1-m%2][s[i].x]=1; } int main() { n=read(),m=read(); prework(); fo(i,m,n) { fo(j,1,num) { f[i%2][s[j].x]=0; f[i%2][s[j].y]=0; } fo(j,1,num) { f[i%2][s[j].y]+=f[(i+1)%2][s[j].x]; if(f[i%2][s[j].y]>=inf)f[i%2][s[j].y]%=inf; } } int ans=0; fo(i,1,3000) { ans+=f[n%2][i]; if(ans>=inf)ans%=inf; } cout<<ans<<endl; return 0; }