zoukankan      html  css  js  c++  java
  • HDU5514——容斥原理&&gcd

    题目

    链接

    有n只青蛙,有m块石头,编号为0~m-1,第i只青蛙每次可以跳$a_i$, 刚开始都在0,问,青蛙总共可以跳到的石头之和为多少。其中$t≤20$,$1≤n≤10^4$,$1≤m≤10^9$,$1≤a_i≤10^9$.

    分析

    根据裴蜀定理知,对于一个有n个点的环,每个循环节的长度为n/gcd(n, k),k为每次走的步数。所以青蛙可以达到的石头编号肯定是$gcd(m,a_i)$的倍数,相当于真正步长为$gcd(m,a_i)$.

    当然要容斥一下,不就是奇加偶减吗,枚举所有的项有$2^n$个($n$是gcd的个数),还要加剪枝,如果当前的lcm是gcd[i]的倍数,那么可以不继续容斥下去(也就是对答案没有贡献).

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 
     5 typedef long long ll;
     6 const int maxn = 100000 + 10;
     7 ll n, m;
     8 ll fac[maxn], cnt, sum;
     9 
    10 ll gcd(ll a, ll b)
    11 {
    12     return b == 0 ? a : gcd(b, a % b);
    13 }
    14 ll lcm(ll a, ll b)
    15 {
    16     return a * b / gcd(a, b);
    17 }
    18 
    19 void dfs(int pos, ll tlcm, int sz)
    20 {
    21     //printf("pos:%d  tlcm:%lld  sz:%d
    ", pos, tlcm, sz);
    22     if(tlcm >= m)  return;
    23     if(pos == cnt)
    24     {
    25         if(sz == 0)  return;
    26         if(sz & 1)
    27         {
    28             ll tmp = (m-1) / tlcm;
    29             sum += tmp * (tmp+1) * tlcm / 2;   //o  tlcm  2*tlcm... tmp*tlcm  奇加偶减
    30         }
    31         else
    32         {
    33             ll tmp = (m-1) / tlcm;
    34             sum -= tmp * (tmp+1) * tlcm / 2;   //o  tlcm  2*tlcm... tmp*tlcm
    35         }
    36         return;
    37     }
    38     if(tlcm % fac[pos] == 0)  return;
    39     dfs(pos+1, tlcm, sz);
    40     dfs(pos+1, lcm(tlcm, fac[pos]), sz+1);
    41 }
    42 
    43 int main()
    44 {
    45     int T, kase = 0;
    46     scanf("%d", &T);
    47     while(T--)
    48     {
    49         scanf("%lld%lld", &n, &m);
    50         bool flag= false;
    51         for(int i = 0;i < n;i++)
    52         {
    53             ll tmp;
    54             scanf("%lld", &tmp);
    55             fac[i] = gcd(tmp, m);
    56             if(fac[i] == 1)  flag = true;
    57         }
    58         printf("Case #%d: ", ++kase);
    59         if(flag)
    60         {
    61             printf("%lld
    ", (m-1) * m / 2);
    62         }
    63         else
    64         {
    65             sort(fac, fac+n);
    66             cnt = unique(fac, fac+n) - fac;
    67             sum = 0;
    68             dfs(0, 1, 0);
    69             printf("%lld
    ", sum);
    70         }
    71     }
    72     return 0;
    73 }

    网上更多的解法是分析m的因子,求贡献。(然而没有看懂

    参考链接:http://www.acmtime.com/?p=864

  • 相关阅读:
    《JavaScript高级程序设计》扩展关于动态原型
    “三角边”的那点事儿
    请允许我说:数学是如此美丽!
    球面模型分解及仿flash标签云
    关于Javascript模块化和命名空间管理
    我所了解的关于JavaScript定义类和对象的几种方式
    正因为我们是前端,所以代码更需要优雅
    “作弊”还是创意?伪3D
    mybatis常用jdbcType数据类型以及对应的JavaType
    mdx之计算成员和命名集
  • 原文地址:https://www.cnblogs.com/lfri/p/11181617.html
Copyright © 2011-2022 走看看