code froce 577B DP

给两个数n(n <= 1e6), m ( m <= 1e3 ), 问能否在n个数里找到一些数 让他们的和相加能被m整除

思路: 把所有的n变为在m的剩余系下的数

1. n > m 此时在m的剩余系下一定存在两个相等的数 那他们之差一定是0 所以此时一定存在能被m整除 (抽屉原理)

2. n <= m

跟01背包问题类似

DP设计的转移方程为

f[i][j] = f[i - 1][j] || f[i - 1][(j - a + m) % m]

前一个式子指在前面的所有数中是否存在和被m整除

第二个式子指在前面所有数中是否存在一个和加上当前这个数字能被m整除 (j != a)

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <algorithm>
 5 using namespace std;
 6
 7 const int MaxN = 1000;
 8 int a, n, m;
 9 bool f[MaxN + 5][MaxN + 5];
10
11 int main()
12 {
13     scanf("%d %d", &n, &m);
14     if (n > m)
15     {
16         printf("YES");
17         return 0;
18     }
19     else
20     {
21         for (int i = 1; i <= n; i++)
22         {
23             scanf("%d", &a); a %= m;
24             f[i][a] = 1;
25             for (int j = 0; j <= m - 1; j++)
26             if (j != a) f[i][j] = f[i - 1][j] || f[i - 1][(j - a + m) % m];
27         }
28         printf(f[n][0] ? "YES" : "NO");
29     }
30 }
时间: 2024-10-29 14:08:16

code froce 577B DP的相关文章

CSU1620: A Cure for the Common Code(KMP+区间DP)

Description Input Output Sample Input abcbcbcbca abbbcdcdcdabbbcdcdcd 0 Sample Output Case 1: 7 Case 2: 11 HINT Source 题意:把字符串简化,问简化得到的最短长度是多少 思路:要简化首先要求循环节,这里用kmp解决,而要求所有简化中最短的的话,用区间dp可以求得 <pre name="code" class="cpp">#include &

HDU 5375 Gray code (简单dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5375 题面: Gray code Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 626    Accepted Submission(s): 369 Problem Description The reflected binary cod

CSU 1620: A Cure for the Common Code (区间DP KMP预处理)

链接 : http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1620 题意 : 给一个字符串 问怎么压缩字符串使得最终个数最小 具体怎么压缩请参照图示 很好明白. 题目就是需要找到 对于每个后缀 看成一个新字符串 找出它的前缀的最小循环节. 过程和大白书 P213页 是一样的,只需要对每个后缀跑一遍KMP求出周期. 剩下的过程就是区间DP了. dp[i][j] = min ( dp[i][k], dp[k+1][j] ); 如果i - j这一段存在

!CodeForces 543A Writing Code --DP--(三维dp,滚动数组)

题意:n个程序员一起写m行代码,第i个程序员每写一行有a[i]个bug,求总bug不超过b的分配方案有多少种 分析:这题很像完全背包,不过求的不是最大/最小bug数,求的是bug数小于上限的分配方案.所以这题要用三维dp dp[i][j][k]表示前i个个程序员总共写了j行代码产生了k个bug时的plan数,这题有两种转移:1)第i个程序员再写一行:2)换第i+1号程序员写 所以方程:dp[i][j][k]=dp[i-1][j][k]+dp[i][j-1][k-a[i]],注意:程序员可能一行都

ZOJ 3494 BCD Code (数位DP,AC自动机)

题意: 将一个整数表示成4个bit的bcd码就成了一个01串,如果该串中出现了部分病毒串,则是危险的.给出n个病毒串(n<=100,长度<21),问区间[L,R]中有几个数字是不含病毒串的(结果需要取模)?(0<L<=R<=10200) 思路: 区间非常大,怎样暴力统计都是不科学的.首先确定状态,按传统,一维必定是位数,二维就是压缩的状态了,如果长度为20个bit的话,200*104万的数组是不行的.类似多模式串匹配问题,病毒串可以构建成AC自动机,那么每个点可以代表一个独立

BZOJ 1037 生日聚会(神DP)

这题的DP很难想,定义dp[i][j][a][b]表示用了i个男生,j个女生,任一连续的后缀区间内,男生比女生最多多a人,女生比男生最多多b人. 转移就是显然了. # include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # include <stack&

POJ 3356 AGTC(DP求字符串编辑距离)

给出两个长度小于1000的字符串,有三种操作,插入一个字符,删除一个字符,替换一个字符. 问A变成B所需的最少操作数(即编辑距离) 考虑DP,可以用反证法证明依次从头到尾对A,B进行匹配是不会影响答案的 令dp[i][j]表示A[i]~[lenA]变成B[j]~[lenB]的最优解. 如果把B[j]插入到A[i]前,dp[i][j]=dp[i][j+1]+1 如果删除A[i],dp[i][j]=dp[i+1][j]+1. 如果A[i]==B[j], dp[i][j]=dp[i+1][j+1].

XTU 1233 Coins(DP)

题意: n个硬币摆成一排,问有连续m个正面朝上的硬币的序列种数. 很明显的DP题.定义状态dp[i][1]表示前i个硬币满足条件的序列种数.dp[i][0]表示前i个硬币不满足条件的序列种数. 那么显然有dp[i][1]=dp[i-1][1]*2+dp[i-1-m][0]. 如果前i-1个硬币满足条件,那么第i个硬币无论怎么样都满足条件.如果前i-1-m个硬币不满足条件,那么只需要再添加m个正面朝上的硬币即可. dp[i][0]=2^i-dp[i][1]. 于是最后的答案就是dp[n][1].

HDU 6006 Engineer Assignment:状压dp

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6006 题意: 在Google中,有个n项目,m个专家.第i个项目涉及c[i]个领域,分别为a[i][0]...a[i][c[i]-1].第i个专家精通d[i]个领域,分别为b[i][0]...b[i][d[i]-1]. 如果要完成一个项目,则这个项目所涉及到的每一个领域都必须至少有一个精通该领域的专家.你作为director,可以任意分配专家,但一个专家只能去做一个项目.问你最多能够完成多少个项目.