zoukankan      html  css  js  c++  java
  • Codeforces 577B Modulo Sum:数学 结论【选数之和为m的倍数】

    题目链接:http://codeforces.com/problemset/problem/448/C

    题意:

      给你n个数字,给定m。

      问你是否能从中选出若干个数字,使得这些数字之和为m的倍数。

    题解:

      其实就是要找一些数字,使得之和mod m为0。

      开一个vector,存当前已经能够构成的数字之和mod m之后的值。

      一开始vector为空,然后枚举n个数字a[i],对于每个数字枚举当前vector中的值v[i],将没有出现过的(a[i]+v[i])%m值加入vector中。

      最后判断下vector中有没有0就好。

      然而直接做是O(nm)的过不了。

      这时候就有一个结论:

        当n>m时,一定能够找出一些数字,使得它们之和mod m为0。

      证明:

        令sum[i]为数字a[1 to i]的和mod m后的值。

        显然,一定有一对(i,j)使得sum[i]==sum[j] (i<j)。

        所以有∑ a[i+1 to j] mod m == 0。得证。

      这样当n>m的时候特判一下直接输出,否则再跑上面的做法。

      这样复杂度就成O(m^2)的了。

     

    AC Code:

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #include <vector>
     5 #define MAX_M 1005
     6 
     7 using namespace std;
     8 
     9 int n,m;
    10 int vis[MAX_M];
    11 vector<int> v;
    12 
    13 int main()
    14 {
    15     cin>>n>>m;
    16     if(n>m)
    17     {
    18         cout<<"YES"<<endl;
    19         return 0;
    20     }
    21     memset(vis,false,sizeof(vis));
    22     int x;
    23     for(int i=1;i<=n;i++)
    24     {
    25         cin>>x;
    26         x%=m;
    27         for(int j=0,t=v.size();j<t;j++)
    28         {
    29             int now=(v[j]+x)%m;
    30             if(!vis[now])
    31             {
    32                 v.push_back(now);
    33                 vis[now]=true;
    34             }
    35         }
    36         if(!vis[x])
    37         {
    38             v.push_back(x);
    39             vis[x]=true;
    40         }
    41     }
    42     if(vis[0]) cout<<"YES"<<endl;
    43     else cout<<"NO"<<endl;
    44 }
  • 相关阅读:
    [转]解决ORACEL数据库“exp导出老是出现ORA-00904”
    教程
    [转]web初学者需要掌握哪些技术
    sublime的使用技巧
    安装Sublime Text
    memcached内存分类机制
    Java生产者和消费者
    一致性哈希原理及应用浅析
    Java线程状态分析
    Java多线程中断机制
  • 原文地址:https://www.cnblogs.com/Leohh/p/8251667.html
Copyright © 2011-2022 走看看