zoukankan      html  css  js  c++  java
  • ACM-ICPC 2015 沈阳赛区现场赛 F. Frogs && HDU 5514(容斥)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5514

    题意:有m个石子围成一圈, 有n只青蛙从跳石子, 都从0号石子开始, 每只能越过xi个石子。问所有被至少踩过一次的石子的序号之和。 

    题解:根据裴蜀定理每个青蛙可以跳到的最小石子编号为 gcd(xi,m) = bi,所有小于 m 的 bi 的倍数都是可以到达的石头。显然所有 bi 都为 m 的因子,标记 m 中所有能到达的因子,进行容斥,比如因子2、3、6都可以到达,计算 2 和 3 的倍数的时候 6 重复算了 1 次,那么可以在计算 2 和 3 的时候标记他们的倍数已经计算了 1 次,然后每个因子的贡献是 num1 - num2。详见代码~

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 #define ull unsigned long long
     5 #define mst(a,b) memset((a),(b),sizeof(a))
     6 #define pii pair<int,int>
     7 #define pi acos(-1)
     8 #define pb push_back
     9 const double eps = 1e-6;
    10 const int INF = 0x3f3f3f3f;
    11 const int MAXN = 1e5 + 10;
    12 vector<int>vec;
    13 int num1[MAXN], num2[MAXN];
    14 
    15 void init(int m) {
    16     mst(num1, 0);
    17     mst(num2, 0);
    18     vec.clear();
    19     for(int i = 1; i <= sqrt(m); i++) {
    20         if(m % i == 0) {
    21             vec.pb(i);
    22             if(i != m / i)
    23                 vec.pb(m / i);
    24         }
    25     }
    26     sort(vec.begin(), vec.end());
    27 }
    28 
    29 ll cal(int a1, int n) {
    30     return (ll)n * (ll)(n + 1) / 2 * (ll)a1;
    31 }
    32 
    33 int main() {
    34 #ifdef local
    35     freopen("data.txt", "r", stdin);
    36 #endif
    37     int cas = 1;
    38     int t;
    39     scanf("%d", &t);
    40     while(t--) {
    41         int n, m;
    42         scanf("%d%d", &n, &m);
    43         init(m);
    44         for(int i = 0; i < n; i++) {
    45             int x;
    46             scanf("%d", &x);
    47             int temp = __gcd(x, m);
    48             int pos = lower_bound(vec.begin(), vec.end(), temp) - vec.begin();
    49             num1[pos] = 1;
    50         }
    51         for(int i = 0; i < vec.size(); i++) {
    52             if(!num1[i]) continue;
    53             for(int j = i + 1; j < vec.size(); j++)
    54                 if(num1[j] == 0 && vec[j] % vec[i] == 0) num1[j] = 1;
    55         }
    56         ll ans = 0;
    57         for(int i = 0; i < vec.size(); i++) {
    58             int num = num1[i] - num2[i];
    59             ans = ans + cal(vec[i], m / vec[i] - 1) * num;
    60             for(int j = i; j < vec.size(); j++)
    61                 if(vec[j] % vec[i] == 0) num2[j] += num;
    62         }
    63         printf("Case #%d: %lld
    ", cas++, ans);
    64     }
    65     return 0;
    66 }
  • 相关阅读:
    java异常笔记
    CORBA IOR学习
    CORBA GIOP消息格式学习
    一个简单的CORBA例子
    Chrome 调试动态加载的js
    Android高效加载大图、多图解决方案,有效避免程序OOM(转)
    安卓开发笔记——打造万能适配器(Adapter)
    安卓开发笔记——个性化TextView(新浪微博)
    安卓开发笔记——关于Handler的一些总结(上)
    安卓开发笔记——关于AsyncTask的使用
  • 原文地址:https://www.cnblogs.com/scaulok/p/9751488.html
Copyright © 2011-2022 走看看