CodeForces 577BModulo Sum

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForces 577BModulo Sum相关的知识,希望对你有一定的参考价值。

题意

给你n(1 ≤ n ≤ 106)个数a1..an(0 ≤ ai ≤ 109),再给你m( 2 ≤ m ≤ 103)如果n个数的子集的和可以整除m,则输出YES,否则NO。

分析

分两种情况:

  当n>m时,s[i]表示前i张钱共多少钱,s[i]%m的取值为0到m-1,由抽屉原理可知,s[i]一定有重复的,假如重复的是s[l]和s[r],那么s[r]-s[l]也就是l+1到r这些钱加起来就是m 的倍数。故答案为YES。

  当n≤m时,我们用dp[i][j]==1表示前i张钱可以得到对m取余为j的价格,dp[i][a%m]=1;dp[i][j]=max(dp[i-1][j],dp[i-1][(m+j-a[i]%m)%m])(j!=a%m,0≤j<m),也就是多了第i张钱能否得到对m取余为j的价格。一旦得到dp[i][0]==1,答案就是YES就不用继续算了。当时这样太浪费空间了,也开不了那么大数组,i最大为106。只要保存上一次的和这一次的就够了。

  另一种是直接推,根据之前可得到的余数推出这一轮可得到的余数。

代码

dp代码

#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,a;
int dp[2][1005];
int main()
{
    scanf("%d%d",&n,&m);
    if(n>m)dp[0][0]=1;
    else
        for(int i=1; i<=n; i++)
        {
            for(int j=0; j<m; j++)dp[1][j]=0;
            scanf("%d",&a);
            dp[1][a%m]=1;

            for(int j=0; j<m; j++)
            {
                if(dp[1][0])break;
                if(j!=a%m)
                    dp[1][j]=max(dp[0][j],dp[0][(m+j-a%m)%m]);
            }
            for(int j=0; j<m; j++)
                dp[0][j]=dp[1][j];
        }
    if(dp[0][0]) printf("YES");
    else printf("NO");
    return 0;
}

另一种代码

#include<cstdio>
#include<cstring>
int n,m;
int a;
int mark[1005],t[1005];
int main()
{
    scanf("%d%d",&n,&m);
    if(n>m)t[0]=1;
    else
        while(n--)
        {
            scanf("%d",&a);
            memset(mark,0,sizeof(mark));
            mark[a%m]=1;
            for(int i=0; i<m; i++)
            {
                if(t[0]) break;
                if(t[i]) mark[(a%m+i)%m]=1;
                //如果之前可得到%m=i的价格,那现在就可得到(a%m+i)%m的价格
            }
            for(int i=0; i<m; i++)
            {
                if(t[i]==0) t[i]=mark[i];
                //保存这一轮的。不能合并到上面一起写
            }
        }
    if(t[0]) printf("YES\n");
    else printf("NO\n");
    return 0;
}

以上是关于CodeForces 577BModulo Sum的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces 577B Modulo Sum:数学 结论选数之和为m的倍数

Henu ACM Round#18 BModulo Sum

CodeForces 577B 模和vecto

Codeforces 577A - Multiplication Table

Codeforces Round #577 (Div. 2)

Codeforces Round #577 (Div. 2) (ABC)