zoukankan      html  css  js  c++  java
  • fzu2204 dp


    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
    ",cc,1<<n);
                }
                else if(n<=15){
                int ans=solve(n);
                printf("Case #%d: %d
    ",cc,ans);
                }else{int d=solve2(n);
                printf("Case #%d: %d
    ",cc,d);
                }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    linux命令
    常用正则表达式总结
    List集合对象根据字段排序
    IO字 节流/字符流 读取/写入文件
    Jquery广告浮动效果小案例
    拿到添加对象的id号方法
    Jquery省市区三级联动案例
    JAVA集合迭代遍历和特性介绍
    Listener监听器使用小案例
    java中用过滤器解决字符编码问题
  • 原文地址:https://www.cnblogs.com/Opaser/p/4857586.html
Copyright © 2011-2022 走看看