HDU 5514 Frogs 容斥原理
Posted legend_PawN
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 5514 Frogs 容斥原理相关的知识,希望对你有一定的参考价值。
n个青蛙在环形的m个编号为0到m-1的石头上跳,不同的青蛙一次跳过不同数量的石头,问最后这n个青蛙能够跳到的石头的序号之和。
容易得知,每次跳x个石头的青蛙,最终只会落在标号为gcd(x,m)的倍数的石头上,但不同青蛙的情况会有重复,所以需要进行容斥。
首先把m的因数打表,求出每一个gcd(x,m),建立vis[i]=1表示需要对第i个因子进行计数,num[i]代表该因数在前i个因子中被加的个数。
vis[i]-num[i]代表当前第i个因数需要容斥的系数,加加减减即可。
AC代码:
#include <bits/stdc++.h>
typedef long long ll;
const int N=1e5+10;
int vis[N],num[N],p[N];
using namespace std;
int gcd(int a,int b)
return b==0 ? a : gcd(b,a%b);
int main()
//freopen("input.txt","r",stdin);
int T,cnt=0;
scanf("%d",&T);
while(T--)
memset(num,0,sizeof(num));
memset(vis,0,sizeof(vis));
int n,m;
scanf("%d%d",&n,&m);
int k=0;
for(int i=1;i*i<=m;i++)
if(m%i==0)
p[k++]=i;
if(i*i!=m)
p[k++]=m/i;
sort(p,p+k);
for(int i=1;i<=n;i++)
int x;
scanf("%d ",&x);
x=gcd(x,m);
for(int i=0;i<k;i++)
if(p[i]%x==0)
vis[i]=1;
vis[k-1]=0;
ll ans=0;
for(int i=0;i<k;i++)
if(vis[i]!=num[i])
ans+=1LL*m*((m-1)/p[i])/2*(vis[i]-num[i]);
int tmp=vis[i]-num[i];
for(int j=i;j<k;j++)
if(p[j]%p[i]==0)
num[j]+=tmp;
printf("Case #%d: %lld\\n",++cnt,ans);
return 0;
以上是关于HDU 5514 Frogs 容斥原理的主要内容,如果未能解决你的问题,请参考以下文章