2015 ACM/ICPC Asia Regional Shenyang Online 1007 hdu 5456 Matches Puzzle Game

Matches Puzzle Game

Time Limit: 3000/2000 MS (Java/Others)    Memory Limit: 65535/102400 K (Java/Others)
Total Submission(s): 118    Accepted Submission(s): 78


Problem Description
As an exciting puzzle game for kids and girlfriends, the Matches Puzzle Game asks the player to find the number of possible equations  AB=C  with exactly  n (5n500)  matches (or sticks).

In these equations,  A,B  and  C  are positive integers. The equality sign needs two matches and the sign of subtraction needs just one. Leading zeros are not allowed.

Please answer the number, modulo a given integer  m (3m2×109) .
 

Input
The input contains several test cases. The first line of the input is a single integer  t  which is the number of test cases. Then  t (1t30)  test cases follow.

Each test case contains one line with two integers  n (5n500)  and  m (3m2×109) .
 

Output
For each test case, you should output the answer modulo  m .
 

Sample Input
  
  
4 12 1000000007 17 1000000007 20 1000000007 147 1000000007
 

Sample Output
  
  
Case #1: 1 Case #2: 5 Case #3: 38 Case #4: 815630825


题意:给你n根火柴,要求你拼出一个a-b=c的图案,并且a,b,c均为正数,问总共多少种方案数

解法:首先先把'-'和'='的三根火柴减掉,然后直接数位DP即可。dp[i][j][k],i表示使用了多少根火柴,j是一个二进制的表示,表示此时是否有借位,k是三个二进制的表示,分别表示此时c是否已经枚举完了,b是否已经枚举完了,a是否已经枚举完了。然后枚举a,b每位上的数字即可。

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
long long dp[505][2][8],mod;
bool vis[505][2][8];
int cnt[]= {6,2,5,5,4,5,6,3,7,6};  
long long dfs(int n,int jie,int sta)
{
	if(n==0)
	{
		vis[n][jie][sta]=true;
		if(jie==0&&sta==7)dp[n][jie][sta]=1;
		else dp[n][jie][sta]=0;
	}
	if(vis[n][jie][sta])return dp[n][jie][sta];
	dp[n][jie][sta]=0;
	for(int i=0;i<10;i++)
	{
		for(int j=0;j<10;j++)
		{
			bool vs[8]={false};
			int xjie=(i-jie>=j?0:1);
			int l=(i+10*xjie-jie-j);
			if((sta&1)&&l>0)continue;
			if((sta&2)&&j>0)continue;
			
			int sum=cnt[i];
			if(sta&2);
			else sum+=cnt[j];
			if(sta&1);
			else sum+=cnt[l];
			if(sum>n)continue;
			for(int k=0;k<8;k++)
			{
				int new_sta=0;
				if((k&4)&&i>0&&sum==n&&xjie==0)new_sta|=4;
				if((k&2)&&j>0)new_sta|=2;
				if((k&1)&&l>0)new_sta|=1;
				
				if(!vs[new_sta])
				{
					vs[new_sta]=1;
					dp[n][jie][sta]+=dfs(n-sum,xjie,new_sta|sta);
					dp[n][jie][sta]%=mod;
				}
			}
		}
	}
	vis[n][jie][sta]=true;
	return dp[n][jie][sta];
}
int main()
{
	int T,cas=0;
	scanf("%d",&T);
	int n;
	while(T--)
	{
		scanf("%d%lld",&n,&mod);
		for(int i=0;i<=n;i++)
			for(int j=0;j<2;j++)
				for(int l=0;l<8;l++)
					vis[i][j][l]=false;
		printf("Case #%d: %lld\n",++cas,dfs(n-3,0,0));
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值