zoukankan      html  css  js  c++  java
  • 【Henu ACM Round#18 B】Modulo Sum

    【链接】 我是链接,点我呀:)
    【题意】

    在这里输入题意

    【题解】

    m比较小 <=1000

    a[i]直接看成a[i]%m就可以了。

    有n个0..999之间的整数。。

    如果有一个0那么就直接输出Yes.

    否则要用那些数字凑0

    则用cnt[0..999]记录每个数字出现的个数。
    即n个物品,每个物品cnt[i]个。
    然后凑和为0

    ->多重背包。

    但每个物品的数量可能很多。
    所以加一个二进制优化就好了。
    把每个物品的数量转化成二进制。

    转换成01背包的问题。
    (物品的数目大概在1000*log2(1e6)的样子

    然后容量是1000.

    这时候就可以做了。

    另解
    如果n>m的话。
    前缀和数组中肯定有sum[i]%m和sum[j]%m相同。
    (抽屉原理,每个数字在0..m-1之间,然后有m+1个数字的话,显然不可能每个数字都相同。
    则i+1..j之间的和就是m的倍数了。
    所以直接输出YES.
    否则做一个O(M^2)的背包就好。

    【代码】

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    
    const int M = 1e3+10;
    
    bool f[2][M];
    int a[M],n,m;
    vector<int> v;
    
    int main()
    {
        ios::sync_with_stdio(0),cin.tie(0);
        #ifdef LOCAL_DEFINE
            freopen("rush.txt","r",stdin);
        #endif
        cin >> n >> m;
        for (int i = 1;i <= n;i++) {
                int x;cin >>x;x%=m;
                a[x]++;
        }
    
        if (a[0]>0){
            cout<<"YES"<<endl;
            return 0;
        }
    
        for (int i = 1;i < m;i++)
            if (a[i]>0){
                int temp = 1;
                while (a[i]>=temp){
                    v.push_back((1LL*temp*i)%m);
                    a[i]-=temp;
                    temp*=2;
                }
                if (a[i]>0) v.push_back((1LL*a[i]*i)%m);
            }
        if (!v.empty()){
            f[0][v[0]] = 1;
            if (v[0]==0) return cout<<"YES"<<endl,0;
            for (int i = 1;i <(int)v.size();i++){
                for (int j = 0;j < m;j++) f[i&1][j] = 0;
                for (int j = 1;j <= m-1;j++)
                    if (f[(i&1)^1][j]){
                        int k = (j+v[i])%m;
                        f[i&1][j] = 1;
                        f[i&1][k] = 1;
                    }
                f[i&1][v[i]] = 1;
                if (f[i&1][0]) return cout<<"YES"<<endl,0;
            }
        }
        cout<<"NO"<<endl;
        return 0;
    }
    
  • 相关阅读:
    241. Different Ways to Add Parentheses java solutions
    89. Gray Code java solutions
    367. Valid Perfect Square java solutions
    46. Permutations java solutions
    116. Populating Next Right Pointers in Each Node java solutions
    153. Find Minimum in Rotated Sorted Array java solutions
    判断两颗树是否相同
    求二叉树叶子节点的个数
    求二叉树第k层的结点个数
    将二叉排序树转换成排序的双向链表
  • 原文地址:https://www.cnblogs.com/AWCXV/p/8376551.html
Copyright © 2011-2022 走看看