• Hdu 5514 Frogs (容斥原理)


    题目链接:

      Hdu 5514 Frogs

    题目描述:

      有n只青蛙,m个石头(围成圆圈)。第i只青蛙每次只能条ai个石头,问最后所有青蛙跳过的石头的下标总和是多少?

    解题思路:

      第一反应就是容斥,也是没谁了。但是重现赛的时候并没有做出来,自己写了一个容斥然后挂掉了,今天看到大神的方法,感觉这种处理方法有点神!(还是见的题目太少,太弱了)
      第i只青蛙只能走到gcd(ai, m)的位置,我们就可以把m的因子提取出来,然后对青蛙能走到的因子位置打标记。青蛙能走到vis[i]因子位置就把vis[i]标记为1,然后num[i]表示m的第i个因子泪加的次数。如果vis[i]!=num[i]的话,就更新num。因子的个数大概是log2(m),所以时间复杂度大概为O(log2(m)2)。

     1 #include <cmath>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <iostream>
     5 #include <algorithm>
     6 using namespace std;
     7 typedef __int64 LL;
     8 const int maxn = 100010;
     9 
    10 int p[maxn], vis[maxn], num[maxn];
    11 int gcd (int a, int b)
    12 {
    13     return b==0 ? a : gcd(b, a%b);
    14 }
    15 
    16 int main ()
    17 {
    18     int T;
    19     scanf ("%d", &T);
    20     for (int t=1; t<=T; t++)
    21     {
    22         int n, m, cnt = 0;
    23         scanf ("%d %d", &n, &m);
    24         for (int i=1; i<=sqrt(m); i++)
    25         {
    26             if (m % i == 0)
    27             {
    28                 p[cnt ++] = i;
    29                 if (i * i != m)
    30                     p[cnt ++] = m / i;
    31             }
    32         }
    33         sort (p, p+cnt);
    34         int u;
    35         memset (vis, 0, sizeof(vis));
    36         memset (num, 0, sizeof(num));
    37         for (int i=0; i<n; i++)
    38         {
    39             scanf ("%d", &u);
    40             int temp = gcd (u, m);
    41             for (int j=0; j<cnt; j++)
    42             {
    43                 if (p[j] % temp == 0)
    44                     vis[j] = 1;
    45             }
    46         }
    47         vis[cnt-1] = 0;
    48         LL ans = 0;
    49         for (int i=0; i<cnt; i++)
    50         {
    51             if (vis[i] != num[i])
    52             {
    53                 LL temp = m / p[i];
    54                 ans += temp * (temp - 1) / 2 * p[i] * (vis[i] - num[i]);
    55                 temp = vis[i] - num[i];
    56                 for (int j=i; j<cnt; j++)
    57                     if (p[j] % p[i] == 0)
    58                     num[j] += temp;
    59             }
    60         }
    61         printf ("Case #%d: %I64d
    ", t, ans);
    62     }
    63     return 0;
    64 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    Thinkphp5+PHPExcel实现批量上传表格数据
    使用ECharts画K线图
    ThinkPHP5+Layui实现图片上传加预览
    SVN使用教程总结
    JS内置对象方法
    头像上传【实用php】
    Sublime Text 3 快捷键总结
    javascript--基础 三元表达式
    javascript---运算符、表达式、递增、比较运算符、逻辑运算符
    导入dmp的sql语句
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4929642.html
Copyright © 2020-2023  润新知