题意:求由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;
}