n个有标号的球围成一个圈。每个球有两种颜色可以选择黑或白染色。问有多少种方案使得没有出现连续白球7个或连续黑球7个。
对方案数mod 2015,球最多有100000个。
 分析
考虑对于非环状球的答案计算,可以设sum(i,k)表示第i个球为k色时的方案数。其计算非常显然
sum(i,k)=1≤j≤6∑sum(i−j,1−k)
接下来考虑收尾相接后需要排除的情况,即收尾同色球长度相加超过6的情况,这可以直接枚举。
首取i个末取j个同色,从答案中删除此时剩下球的方案数,注意剩下的球的首末球颜色不能和已经枚举的颜色同色。鉴于这种要求,我们退回到sum的递推公式处,决定sum的边界条件为首个球固定为黑色,这样就能很方便的确定球的颜色,且根据对称性答案可以直接x2得到。
题就做完了。
 代码
淦,为什么当时没写。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
   | #include <iostream> using namespace std; const int MAXN=100010; const int P=2015;
  int sum[MAXN][2]; int main(){     int kase;cin>>kase;     sum[0][1]=1;     for(int i=1;i<=100000;i++){         for(int j=1;j<=min(i,6);j++){             (sum[i][1]+=sum[i-j][0])%=P;             (sum[i][0]+=sum[i-j][1])%=P;         }     }     sum[0][1]=0;     int cnt=0;     while(kase--){         int nlen;cin>>nlen;         int ans=(sum[nlen][0]+sum[nlen][1])%P;         if(nlen>=7)             for(int i=1;i<=6;i++)                 for(int j=1;j<=6;j++)                     if(i+j>=7 && nlen-i-j>=0)                         ans=(ans-sum[nlen-i-j][0])%P;         cout<<"Case #"<<++cnt<<": "<<((ans*2)%P+2015)%P<<endl;     }     return 0; }
   |