菜菜的喵喵题~

  化序列为矩阵!化腐朽为神奇!左上角为1,往右每次*3,往下每次*2,这样子就把问题转化成了在矩阵里选不相邻的数有几种可能。

  举个矩阵的例子

  1 3 9 27
  2 6 18 54
  4 12 36 108

  这样最多11列,最多17行,那么方案数就可以用状压了。 

  但是我们会发现,矩阵里没有5,所以我们要把5作为左上角再算一次答案,最后把所有矩阵的答案用乘法原理乘起来就好

#include<iostream> 
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath> 
#include<algorithm> 
#define MOD(x) ((x)>=mod?(x)-mod:(x))
using namespace std;
const int maxn=500010,mod=1e9+1;
int n,ans,cnth;
int f[20][1<<11],cntl[20];
bool v[maxn];
inline void read(int &k)
{
    int f=1;k=0;char c=getchar();
    while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar();
    k*=f;
}
inline int find(int x)
{
    cnth=0;memset(cntl,0,sizeof(cntl));
    for(int i=1,fir=x;fir<=n;i++,fir*=2,cnth++)
    for(int j=1,sec=fir;sec<=n;j++,sec*=3,cntl[i]++)v[sec]=1;
    f[0][0]=1;
    for(int i=1;i<=cnth;i++)for(int j=0;j<=(1<<cntl[1])-1;j++)f[i][j]=0;
    for(int i=1;i<=cnth;i++)
    for(int j=0;j<(1<<cntl[i]);j++)
    if(!(j&(j>>1)))
    for(int k=0;k<(1<<cntl[i-1]);k++)
    if(!(k&(k>>1)))if(!(j&k))f[i][j]=MOD(f[i][j]+f[i-1][k]);
    int sum=0;
    for(int i=0;i<=(1<<cntl[cnth])-1;i++)sum=MOD(sum+f[cnth][i]);
    return sum;
}
int main()
{
    read(n);ans=1;
    for(int i=1;i<=n;i++)
    if(!v[i])ans=1ll*ans*find(i)%mod;
    printf("%d\n",ans);
}
View Code

相关文章:

  • 2021-10-06
  • 2022-12-23
  • 2021-05-28
  • 2021-10-05
  • 2022-12-23
  • 2021-09-07
  • 2021-08-08
猜你喜欢
  • 2022-01-08
  • 2021-12-05
  • 2021-05-18
  • 2018-03-15
  • 2022-03-02
  • 2021-09-08
  • 2021-07-17
相关资源
相似解决方案