HDU - 5514 Frogs
题目大意:有n只青蛙,每只青蛙的弹跳能力为ai,他们都从0出发,绕着m个石头围成的圈子跳跃,石头编号为0~m-1,问能被跳到的石头编号之和
具体思路:首先可以发现弹跳能力为ai的青蛙,可以跳到的石头编号是gcd(ai, m)的倍数
枚举m的因子,若某个青蛙可以弹跳的石头编号中有该因子,那证明编号为这个因子的石头一定会被跳到
num[i]记录编号为i的石头被跳了几次,如果被跳的次数不等于应跳的次数(不为0或1),则减去多余的影响
AC代码
#include<bits/stdc++.h> #define int long long using namespace std; int T,i,j,n,m,vis[100000],num[100000],x,t; int gcd(int a,int b) { if(b==0)return a; else return gcd(b,a%b); } map <int,int> mp; vector <int> d; main() { scanf("%lld",&T); for (int tt=1; tt<=T; tt++) { scanf("%lld%lld",&n,&m); int M=(int)sqrt(m); for (i=1; i<=M; i++) { if(m%i==0) { d.push_back(i); if(m/i!=i)d.push_back(m/i); } } sort(d.begin(),d.end()); memset(vis,0,sizeof vis); memset(num,0,sizeof num); for(i = 1; i <= n; ++i) { scanf("%lld",&x); t=gcd(x,m); M=d.size(); for(j=0; j<M; ++j)if(d[j]%t==0)vis[j]=1; } int ans=0; M=d.size()-1; for(i = 0; i<M; ++i) if(vis[i]!=num[i]) { t=(m-1)/d[i]; ans+=t*(t+1)/2*d[i]*(vis[i]-num[i]); t=vis[i]-num[i]; for(j = i; j <M; ++j) if(d[j]%d[i]==0)num[j]+=t; } printf("Case #%lld: %lld\n",tt,ans); } return 0; }