hdu5389(DP)

题意:

给出n个人的id,有两个门,每一个门有一个标号。我们记作a和b,如今我们要将n个人分成两组,进入两个门中,使得两部分人的标号的和(迭代的求,直至变成一位数。我们姑且叫做求“和”操作~)各自等于a和b,问有多少种分法。

思路:

非常easy想到。假设能找到满足题意的解。一定满足a和b的和等于n个人的标号的和,所以我们仅仅须要推断n个人的标号组成a的情况有多少(或者仅仅推断b,一样),同一时候还要注意能够把n个人都分给a,或者都分给b,这样也是满足的。

详细的细节都在代码里了,一看应该就能懂~~

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

const int maxn=100005;

#define mod 258280327

int SUM(int x,int y)
{
	int tmp=x+y;
	int ans=tmp%9;
	if(ans==0)
		return 9;
	return ans;
}

int num[maxn];
int dp[maxn][10];

int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n,a,b;
		scanf("%d%d%d",&n,&a,&b);
		int sum=0;
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&num[i]);
			sum=SUM(sum,num[i]);
		}
		memset(dp,0,sizeof dp);
		dp[0][0]=1;
		for(int i=1;i<=n;i++)
		{
			for(int j=0;j<=9;j++)
			{
				dp[i][j]+=dp[i-1][j];
				dp[i][SUM(num[i],j)]+=dp[i-1][j];
				dp[i][j]%=mod;
				dp[i][SUM(num[i],j)]%=mod;
			}
		}
		int ans=0;
		if(SUM(a,b)==sum)
		{
			ans+=dp[n][a];
			if(a==sum)
				ans--;
		}
		if(a==sum)
			ans++;
		if(b==sum)
			ans++;
		printf("%d\n",ans);
	}
	return 0;
}
时间: 2025-01-17 16:03:49

hdu5389(DP)的相关文章

多校8-1010 HDU5389 (dp

题目:每个人有1~9的编号,有两个门,一帮人能进门,当且仅当这些人的编号之和与门的编号同余.问把这些人安排到两个门有多少种方法. 思路:比赛的时候有点脑抽,想了好久才发现是个简单dp....只需要统计每个编号的人数,然后dp[i][j]表示前i个编号的人组成j同余的方案数,然后由于每种人选9的倍数个是无影响的,所以每种选择实际上是选x个,x+9,x+18……个,那么转移状态的时候需要计算n个数里选x个,x+9,x+18……个的方案数之和,这个怎么计算呢?利用一个递推式C[n][k]=C[n][k

hdu5389 Zero Escape DP+滚动数组 多校联合第八场

Zero Escape Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 56    Accepted Submission(s): 18 Problem Description Zero Escape, is a visual novel adventure video game directed by Kotaro Uchikos

[hdu5389 Zero Escape]数根的性质,DP

题意:把n个数(1-9)放到A集合和B集合里面去,使得A集合里面的数的数根为a,B集合里面的数的数根为b,也可以只放在A或B任一个集合里面.求方法总数.比如A={2,4,5},则A的数根为[2+4+5]=[11]=[2]=2 思路:一个数为a,则它的数根b=(a-1)%9+1=(digit-1)%9+1,digit是a的十进制各位上的数的和.如果存在解,那么任选一些数放到A集合里面,使得A集合的数根为a,那么B集合的数根一定为b.由公式可知,数根可以转化为余数来做,令dp[i][x]表示考虑前i

hdu5389(2015多校8)--Zero Escape(dp)

题目链接:点击打开链接 题目大意:有A和B两个门,每个门上有一个数字,现在有n个人,每个人手里也有一个数字,现在n个人都要选择一个门进去,要求计算门内的人的数字每一位的和,一直累加到一位.这个数和门代表的数字是相同的.问n个人有多少种走法. 例如 65536 -> 25 -> 7 输入n A B,之后一行输入n个数字代表n个人手中的数字.每个数字都是大于0的 输出种类个数. 对于累加每一位的和到一位的值 = 初始数的每一位的和%9,其中0代表累加的结果是9 首先判断所有人的和%9,是不是(A+

HDU 5542 The Battle of Chibi dp+树状数组

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5542 题意:给你n个数,求其中上升子序列长度为m的个数 可以考虑用dp[i][j]表示以a[i]结尾的长度为j的上升子序列有多少 裸的dp是o(n2m) 所以需要优化 我们可以发现dp的第3维是找比它小的数,那么就可以用树状数组来找 这样就可以降低复杂度 #include<iostream> #include<cstdio> #include<cstring> #include

hdu 1207 汉诺塔II (DP+递推)

汉诺塔II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4529    Accepted Submission(s): 2231 Problem Description 经典的汉诺塔问题经常作为一个递归的经典例题存在.可能有人并不知道汉诺塔问题的典故.汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往

POJ - 3186 Treats for the Cows (区间DP)

题目链接:http://poj.org/problem?id=3186 题意:给定一组序列,取n次,每次可以取序列最前面的数或最后面的数,第n次出来就乘n,然后求和的最大值. 题解:用dp[i][j]表示i~j区间和的最大值,然后根据这个状态可以从删前和删后转移过来,推出状态转移方程: dp[i][j]=max(dp[i+1][j]+value[i]*k,dp[i][j-1]+value[j]*k) 1 #include <iostream> 2 #include <algorithm&

51Nod 1009 数字1的个数 | 数位DP

题意: 小于等于n的所有数中1的出现次数 分析: 数位DP 预处理dp[i][j]存 从1~以j开头的i位数中有几个1,那么转移方程为: if(j == 1) dp[i][j] = dp[i-1][9]*2+pow(10,i-1);else dp[i][j] = dp[i-1][9]+dp[i][j-1]; 然后注意下对于每个询问统计的时候如果当前位为1需要额外加上他后面所有位数的个数,就是n%pow(10,i-1); 这样总复杂度log(n)*10 #include <bits/stdc++.

HDU 3555 Bomb (数位DP)

数位dp,主要用来解决统计满足某类特殊关系或有某些特点的区间内的数的个数,它是按位来进行计数统计的,可以保存子状态,速度较快.数位dp做多了后,套路基本上都差不多,关键把要保存的状态给抽象出来,保存下来. 简介: 顾名思义,所谓的数位DP就是按照数字的个,十,百,千--位数进行的DP.数位DP的题目有着非常明显的性质: 询问[l,r]的区间内,有多少的数字满足某个性质 做法根据前缀和的思想,求出[0,l-1]和[0,r]中满足性质的数的个数,然后相减即可. 算法核心: 关于数位DP,貌似写法还是