码迷,mamicode.com
首页 > 其他好文 > 详细

HDU5514——容斥原理&&gcd

时间:2019-07-13 18:36:38      阅读:97      评论:0      收藏:0      [点我收藏+]

标签:没有   ref   石头   clu   through   while   http   分析   sort   

题目

链接

有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\n", 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\n", (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\n", sum);
70         }
71     }
72     return 0;
73 }

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

 

 

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

HDU5514——容斥原理&&gcd

标签:没有   ref   石头   clu   through   while   http   分析   sort   

原文地址:https://www.cnblogs.com/lfri/p/11181617.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!