• 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 }
  • 相关阅读:
    vscode远程开发
    iframe父子组件传值
    react项目地址栏添加包名
    记一次lombok踩坑记
    Android Adb修改系统时区 NTP 服务器
    ES文件浏览器4.1.9.7.4任意文件浏览漏洞
    SUID提权之python的os.setuid(0)提权
    PHP-8.1.0-dev 后门命令执行
    将博客搬至CSDN
    零基础快速上手HarmonyOS开发1---为什么要学习HarmonyOS?如何能快速上手?HarmonyOS架构解析、和Android深度对比
  • 原文地址:https://www.cnblogs.com/lyqf/p/9801056.html
Copyright © 2020-2023  润新知