大概就是让你找方案数嘛。开始我还以为是一道规律题,然后有愉快地打了一个暴搜打表。
找了十分钟没找出来。www.oeis.org。结果... ...
半点规律没有。然后想了想DP,想不出线性或带log的。
最后实在做不出来了,于是问了个大犇。大犇说这道题要用矩形。尼玛没在逗我。
把题目意思转换一下嘛。就是有了X,就不能有2X和3X。
然后依大犇所言构造一个介样的矩形:
1 | 3 | 9 | 27 |
2 | 6 | 18 | 54 |
4 | 12 | 36 | ... |
8 | 24 | 72 | ... |
16 | 48 | ... | ... |
然后想起炮兵阵地这道题,状压DP即可求出解。
注意到这个矩阵内没有5,7,10... ... ,即以它们为左上角的点的方案没有算进去,于是开vis数组。因为各个矩阵内的数字互不影响,所以用乘法原理。
代码什么的。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <cstring>
#define LL long long int
#define ls (x << 1)
#define rs (x << 1 | 1)
#define fa (x >> 1)
#define MID int mid=(l+r)>>1
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
#define MOD 1000000001
using namespace std;
LL n,vis[101010],f[110][2049],a[21][21],Ans=1,line[40],tmp;
LL gi()
{
LL x=0,res=1;char ch=getchar();
while(ch!='-' && (ch>'9' || ch<'0'))ch=getchar();
if(ch=='-')res=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=(x<<3)+(x<<1)+ch-48,ch=getchar();
return x*res;
}
LL calc(LL x)
{
a[1][1]=x;
for(int i=1;;++i)
{
if(i!=1)
{
a[i][1]=a[i-1][1]*2;
if(a[i][1]>n)
{tmp=i-1;break;}
}
vis[a[i][1]]=1;
for(int j=2;;++j)
{
a[i][j]=a[i][j-1]*3;
if(a[i][j]>n)
{line[i]=j-1;break;}
vis[a[i][j]]=1;
}
}
line[0]=1;
for(int i=0;i<=tmp;++i)
for(int j=0;j<(1<<line[i]);++j)
f[i][j]=0;
line[tmp+1]=0;f[tmp+1][0]=0;f[0][0]=1;
for(int i=0;i<=tmp;++i)
{
for(int j=0,k1=1<<line[i];j<k1;++j)
{
if(f[i][j])
{
if(j & j>>1)continue;
for(int k=0,k2=1<<line[i+1];k<k2;++k)
{
if(j&k)continue;
f[i+1][k]=(f[i+1][k]+f[i][j])%MOD;
}
}
}
}
return f[tmp+1][0];
}
int main()
{
n=gi();
for(LL i=1;i<=n;++i)
if(!vis[i])
Ans=(Ans*calc(i))%MOD;
cout<<Ans;
}