zoukankan      html  css  js  c++  java
  • FZU 2204 7

    题意:

      n个有标号的球围成一个圈。每个球有两种颜色可以选择黑或白染色。问有多少种方案使得没有出现连续白球7个或连续黑球7个?

    思路:

      如果出现连续的8,9...个球同色,那么也必定含有7个同色。需要统计两部分,第一部分是将n个球看成一个序列,在不允许出现连续7个同色球的情况下,统计其可能出现的所有方案数。第二部分是,在第一部分中统计到的,有可能在一个圈的接口处可能出现超过6个球同色的,那么只需要再统计一下这一情况的方案数。问题在于这里。

      序列上肯定不会超过6个同色,所以环的头尾加起来最多有12个同色球,即序列前6个,序列后6个。但是如果n<=12的话,还不会出现环接口处12个同色的情况,需要分类讨论。假设n=8,那么最多可能出现7个同色(根据第一部分的假设),若n=9,最多可能出现8个同色....若n=13,最多可能出现12个同色。先假设序列A={7,8,9,10,11,12}。

      如何求第二部分?假如n=8,那么最多可能出现7个连色,那么就先假设前7个球都是黑色,剩下1个球,只能是白色了,所以方案数为1。但是前7个球可能是白色的,而剩下的1球是黑色的,这只需要将前面的方案数乘以2就行了。而这7个连色的球还可能在环上的不同位置出现,所以还得再乘以(13-7)。其他的大概也是这样推的,只是部分处理可能不同。

     1 //#include <bits/stdc++.h>
     2 #include <iostream>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <map>
     7 #include <algorithm>
     8 #include <vector>
     9 #include <iostream>
    10 #define pii pair<int,int>
    11 #define INF 0x7f3f3f3f
    12 #define LL long long
    13 #define ULL unsigned long long
    14 using namespace std;
    15 const double PI  = acos(-1.0);
    16 const int M=2015;
    17 int cur, dp[2][1<<6], ans[100010], up=1<<6, mod=1<<5;
    18 
    19 void DP(int n)
    20 {
    21     for(int i=1; i<=n; i++)
    22     {
    23         ans[0]=ans[i]=0;
    24         cur^=1;
    25         memset(dp[cur], 0, sizeof(dp[cur]));
    26         for(int s=0,t,v; s<up; s++)
    27         {
    28             v=dp[cur^1][s];
    29             t=(s&(mod-1))<<1;    //取低5位
    30 
    31             if(s+1==up)      //6黑
    32             {
    33                 dp[cur][t]+=v;
    34                 ans[i]+=v;  //只取白色结尾的
    35                 ans[0]+=v;
    36             }
    37             else if(s==0)         //6白
    38             {
    39                 dp[cur][t+1]+=v;
    40                 ans[0]+=v;
    41             }
    42             else
    43             {
    44                 dp[cur][t]+=v;
    45                 dp[cur][t+1]+=v;
    46                 ans[i]+=v;
    47                 ans[0]+=v+v;
    48             }
    49 
    50             dp[cur][t]%=M;
    51             dp[cur][t+1]%=M;
    52             ans[i]%=M;
    53             ans[0]%=M;
    54         }
    55     }
    56 }
    57 
    58 int cal(int n)
    59 {
    60     if(n<7)     return 1<<n;
    61     if(n==7)    return 126;
    62 
    63     memset(dp[cur=0],0,sizeof(dp[cur]));
    64     dp[cur][up-1]=1;   //默认前7个全黑,但是状态只记6位
    65     DP(n);
    66     int ans1=ans[0]*2%M, ans2=0;
    67     for(int k=7; k<=12; k++)    //最多可能取到6+6=12个同颜色的
    68         if(n-k>0)
    69             ans2=(ans2+ans[n-k]*2*(13-k))%M; //枚举13-k个位置
    70 
    71     return (ans1+M-ans2)%M;
    72 }
    73 
    74 
    75 int main()
    76 {
    77     //freopen("input.txt","r",stdin);
    78     int n, t, Case=0;
    79     scanf("%d",&t);
    80     while(t--)
    81     {
    82         scanf("%d",&n);
    83         printf("Case #%d: %d
    ",++Case,cal(n));
    84     }
    85     return 0;
    86 }
    AC代码
  • 相关阅读:
    this指向问题
    b继承a的函数
    如何解决跨域问题
    事件冒泡和阻止事件冒泡
    Spring5(二)——IOC
    MySQL基础(四)——
    MySQL基础(二)——常用命令
    MySQL基础(一)——入门
    Linux(二)——常用命令
    Linux(一)——简介
  • 原文地址:https://www.cnblogs.com/xcw0754/p/4858346.html
Copyright © 2011-2022 走看看