标签:
2015-10-06 19:31:05
n个有标号的球围成一个圈。每个球有两种颜色可以选择黑或白染色。问有多少种方案使得没有出现连续白球7个或连续黑球7个。
每组包含n,表示球的个数。(1 <= n <= 100000)
dp[i][0][x] 表示在第i为填黑色且加上第i位连续的前面有x个黑色的球,dp[i][1][x]表示在第i为填白色且加上第i位连续的前面有x个白色的球
我们只算第一个球为白色,那么最后计算出的个数会等于第一个球去黑色的个数,这个很好理解,只要把他们的颜色相对应的反转一下就好了。然后剩下的好了,
最后的答案 是 dp[n][0-1][1-6] 再减去一些首位连接会超过7个的方案就好了,枚举前几位分别放什么相同的颜色,然后后面减去就好了
#include <iostream> #include <algorithm> #include <cstdio> #include <string.h> using namespace std; const int maxn=100005; const int mod=2015; int dp[maxn][2][7]; int solve(int n){ int ans=0; for(int i=0;i<(1<<n); i++) { int hei=0,bai=0; int bo=1; for(int j=0; j<n; j++){ hei=0;bai=0; for(int k=0; k<7;k++) if( ( 1<<((j+k)%n) ) & i )bai++; else hei++; if(hei>=7||bai>=7){ bo=0;break; } } if(bo)ans++; } return ans%mod; } int solve2(int n) { int ans=0; for(int i=6; i>=1; i--) { ans=(ans+dp[n][0][i]+dp[n][1][i])%mod; } ans=(ans*2)%mod; for(int i=1; i<7; i++) { for(int j=7-i; j<=6; j++) { ans=(ans-(dp[n-i][0][j]+dp[n-i][0][j])%mod+mod)%mod; } } return ans; } int main() { memset(dp,0,sizeof(dp)); dp[1][1][1]=1; for(int i=2; i<=100000; i++) { for(int j=1;j<=6;j++) dp[i][0][1]=(dp[i-1][1][j]+dp[i][0][1])%mod; for(int k=2; k<=6; k++) dp[i][0][k]=dp[i-1][0][k-1]; for(int j=1; j<=6;j++) dp[i][1][1]=(dp[i-1][0][j]+dp[i][1][1])%mod; for(int k=2; k<=6; k++) dp[i][1][k]=dp[i-1][1][k-1]; } int n; int cas; scanf("%d",&cas); for(int cc=1; cc<=cas; cc++) { scanf("%d",&n); if(n<7) { printf("Case #%d: %d\n",cc,1<<n); } else if(n<=15){ int ans=solve(n); printf("Case #%d: %d\n",cc,ans); }else{int d=solve2(n); printf("Case #%d: %d\n",cc,d); } } return 0; }
标签:
原文地址:http://www.cnblogs.com/Opaser/p/4857586.html