FZU 2204 7 dp+预处理

Problem G 7

Accept: 30    Submit: 375
Time Limit: 2000 mSec    Memory Limit : 65536 KB

 Problem Description

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

 Input

第一行有多组数据。第一行T表示组数。(T <= 20)

每组包含n,表示球的个数。(1 <= n <= 100000)

 Output

每组先输出 "Case #x: " (其中x为当前组数) 该行接下来输出方案数。方案数mod 2015。

 Sample Input

271

 Sample Output

Case #1: 126Case #2: 2


题链:http://acm.fzu.edu.cn/contest/problem.php?cid=145&sortid=7


做法 :

dp 一维记录 轮到第几个点了,二维记录 当前连续最长有几个黑色,或者白色,第三维记录 黑色还是白色。

枚举开头是黑色的话,枚举有几个黑的,然后dp过去。对于每个i,当末尾和开头黑色的合 不超过6, 就把答案加到real里面。把所有答案预处理出来。

 


 

 



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <malloc.h>
#include <ctype.h>
#include <math.h>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#include <stack>
#include <queue>
#include <vector>
#include <deque>
#include <set>
#include <map>
#define ll long long//试试


int dp[100010][7][2];//前面 几个连续 0 白连续  1 黑连续
int real[100010];
int mod=2015;
void init()
{
	//开头是 黑的 所有
	
	memset(real,0,sizeof real);
	for(int ji=1;ji<=6;ji++)//前面几个 黑色连续的
	{
		memset(dp,0,sizeof dp);
		if(ji==6)
			dp[6][6][1]=1;//全黑
		for(int bai=1;bai+ji<=6;bai++)
		{
			int nww=6-ji-bai;
			if(nww==1) continue;
			if(nww==0) dp[6][bai][0]++;
			else
				dp[6][bai][0]=(1<<(6-ji-bai-2));
			dp[6][bai][0]%=mod;
		}
		for(int bai=1;bai+ji<=6;bai++)//黑的
		{
			int nww=6-ji-bai;
			if(nww==0)
				continue;
			else if(nww==1)
				dp[6][bai][1]++;//放一个白色的
			else 
				dp[6][bai][1]=(1<<(6-ji-bai-2));//放两个白

			dp[6][bai][1]%=mod;
		}
		
		for(int i=7;i<=100000;i++)
		{
			for(int j=1;j<7;j++)//这个
			{
				dp[i][j][0]+=dp[i-1][j-1][0];//继续放白色
				
				dp[i][1][0]+=dp[i-1][j][1];//之前是黑的


				dp[i][j][1]+=dp[i-1][j-1][1];//继续放黑色

				dp[i][1][1]+=dp[i-1][j][0];//之前放的是白色

				dp[i][j][0]%=mod;
				dp[i][j][1]%=mod;
			}
			
			for(int ii=1;ii<7;ii++)
			{
				real[i]+=dp[i][ii][0];
				
				if(ii+ji<7)
					real[i]+=dp[i][ii][1];


			}
			real[i]%=mod;


			
			//	printf("开头几个黑 %d  答案 %d  \n",ji,real[i]);
		}
	}
}


int main()
{ 
	int t;
	init();
	int cas=1;
	scanf("%d",&t);
	while(t--)
	{
		int n;
		scanf("%d",&n);//
		int ans=0;

		printf("Case #%d: ",cas++);
		 if(n<7)
		 {
			 printf("%d\n",(1<<n));

		 }
		// else if(n==7) 
			 //printf("126\n"); 
		 else
		 {
			 printf("%d\n",real[n]*2%mod); 
		 } 
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值