http://uoj.ac/problem/300

 

预备知识:

C(n,m)是奇数的充要条件是 n&m==m

 

由卢卡斯定理可以推出

选出的任意相邻两个数a,b 的组合数计算C(a,b)必须是奇数

所以可以设dp[i][j] 表示前i个数里面,选的最后一个数是第j个数的方案数

转移的时候,枚举前i-1个数选的最后一个数k,

若C(k,i)是奇数,dp[i][j]+=dp[i-1][k]

时间复杂度:O(n^3)

#include<cstdio>
#include<iostream>

using namespace std;

#define N 20

const int mod=1e9+7;

int a[N];

int dp[N][N];

void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
}

bool judge(int x,int y)
{
    if(!x) return true;
    return (x&y)==y;
}    

int main()
{
    int n;
    read(n);
    for(int i=1;i<=n;++i) read(a[i]);
    dp[0][0]=1;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=i;++j) 
        {
            dp[i][j]=1;
            for(int k=1;k<j;++k)
                if(judge(a[k],a[j])) 
                {
                    dp[i][j]+=dp[i-1][k];
                    dp[i][j]-=dp[i][j]>=mod ? mod : 0;
                }
        }
    int ans=0;
    for(int i=1;i<=n;++i) 
    {
        ans+=dp[n][i]-1;
        ans-=ans>=mod ? mod : 0;
    }
    printf("%d",ans);
}        
View Code

相关文章:

  • 2021-07-09
  • 2022-01-21
  • 2021-05-17
  • 2021-09-16
  • 2021-09-11
  • 2021-11-05
  • 2021-07-27
  • 2021-05-25
猜你喜欢
  • 2021-08-30
  • 2021-12-27
  • 2021-07-11
  • 2022-03-07
  • 2021-09-25
  • 2022-01-25
相关资源
相似解决方案