• hdu 5514Frogs


    gcd+容斥

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn = 1e4 + 10;
     5 ll n,m;
     6 int fac[maxn];
     7 int vis[maxn];
     8 int num[maxn];
     9  
    10 int main()
    11 {
    12     int T;
    13     scanf("%d",&T);
    14     for(int ii = 1; ii <= T; ii ++)
    15     {
    16         memset(vis,0,sizeof(vis));
    17         memset(num,0,sizeof(num));
    18         scanf("%I64d%I64d",&n,&m);
    19         int tot = 0;
    20         for(int i = 1; i * i <= m;i ++)
    21         {
    22             //找到所有m的因子 
    23             if(m % i == 0)
    24             {
    25                 fac[tot ++] = i;
    26                 if(i * i != m)
    27                 fac[tot ++] = m/i;
    28             }
    29         }
    30         //对因子排序 
    31         sort(fac,fac + tot);
    32         tot --;
    33         for(int i = 1; i <= n;i ++)
    34         {
    35             ll x;
    36             scanf("%I64d",&x);
    37             //每只青蛙能跳的石头是石头数与每只青蛙跳的距离的最大公约数的倍数,先找到d最大公约数 
    38             ll d = __gcd(x,m);
    39             //找到所有m因子中该青蛙能跳到的,记录为1 
    40             for(int j = 0; j < tot; j ++)
    41                 if(fac[j] % d == 0)
    42                     vis[j] = 1;
    43         }
    44         ll ans = 0;
    45         for(int i = 0; i < tot; i ++)
    46         {
    47             if(vis[i] != num[i])
    48             {
    49                 ll t = (m - 1)/fac[i];//此处m-1理解为虽然石头是m个,但是石头是从0开始标号的,所以减一。则t可以算出来这个因数在m-1范围内的最大倍数 
    50                 ans += t * (t + 1) / 2 * fac[i] * (vis[i] - num[i]);//等差数列前n项和*要乘的次数 
    51                 //对于t * (t + 1) / 2 * fac[i]这个公式,等差数列前n项和是一个变形,用的是n(a1+an)/2,an=n*a1,变形得到的 
    52                 for(int j = i + 1; j < tot; j ++)//再一次循环,因为前一步加的时候,所有最大公约数的倍数已经加上,所以后面万一重复要减去 
    53                 {
    54                     if(fac[j] % fac[i] == 0)//发现是之前最大公约数的倍数 
    55                     num[j] += vis[i] - num[i];//次数要改变(通过这个公式算正负零,后面统一加上就是答案) 
    56                 }
    57             }
    58         }
    59         printf("Case #%d: %I64d
    ",ii,ans);
    60     }
    61     return 0;
    62 }
  • 相关阅读:
    混合开发的坑(3) ---关于es6
    混合开发的坑(2) ---pdf展示
    混合开发的坑(1) ---ajax请求
    vue.js
    vue中 import引入组件
    vue中 静态文件引用注意事项
    Oracle 数据库链接
    Oracle中的NVL,NVL2,NULLIF以及COALESCE函数使用
    Merge into 使用
    C# —— IList, ArrayList与List的区别详解
  • 原文地址:https://www.cnblogs.com/lyqf/p/9801056.html
Copyright © 2020-2023  润新知