HDU 5514 欧拉函数应用
前置技能:
<=i且与i互质的数的和是phi(i)*i/2
思路:
显然每个人的步数是gcd(a[i],m)
把m的所有因数预处理出来
1~m-1中的每个数 只会被gcd(m,i)筛掉一遍
//By SiriusRen #include <cstdio> #include <algorithm> using namespace std; const int N=100050; typedef long long ll; int cases,n,m,a[N],s[N],tp,I=1; int gcd(int a,int b){return b?gcd(b,a%b):a;} int get_phi(int x){ int t=x; for(int i=2;i*i<=x;i++)if(x%i==0){ t-=t/i; while(x%i==0)x/=i; }if(x>1)t-=t/x; return t; } int main(){ for(scanf("%d",&cases);I<=cases;I++){ long long ans=0;tp=0; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]),a[i]=gcd(a[i],m); sort(a+1,a+1+n); n=unique(a+1,a+1+n)-a-1; for(int i=1;i*i<=m;i++)if(m%i==0){ if(i*i==m)s[++tp]=i; else{ s[++tp]=i; if(i!=1)s[++tp]=m/i; } } for(int i=1;i<=tp;i++) for(int j=1;j<=n;j++)if(s[i]%a[j]==0){ ans+=get_phi(m/s[i]);break; } printf("Case #%d: %lld\n",I,1ll*ans*m/2); } }