T^TOJ - 1251 - ?????TMD - 歐拉函數 - 質因數分解
阿新 • • 發佈:2019-05-16
因數 pri () tac -- bit esp type class
http://www.fjutacm.com/Problem.jsp?pid=1251
想了很久,一開始居然還直接枚舉因子d,計算重復了。
首先你要找與n的最大公因子大於m的x的個數。
\[\sum\limits_{x=1}^n [gcd(x,n)>=m]\]
不能直接枚舉d,d必須是n的因子,否則與n的gcd都不可能是d。
\[\sum\limits_{d=m \& d|n}^n \sum\limits_{x=1}^n [gcd(x,n)==d]\]
後面那個有點眼熟?
\[\sum\limits_{d=m \& d|n}^n \sum\limits_{x=1}^{n/d} [gcd(x,n/d)==1]\]
果然是歐拉函數:
\[\sum\limits_{d=m \& d|n}^n \varphi(n/d)\]
然後,查了一下,因子的個數實在不會太多1e8不到1000個,1e17不到100000個。
那就直接質因數分解然後搜索。
一發AC。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=100000; int pri[N+5],tot,zhi[N+5]; void sieve(int n) { zhi[1]=1; for(int i=2; i<=n; i++) { if(!zhi[i]) pri[++tot]=i; for(int j=1; j<=tot&&i*pri[j]<=n; j++) { zhi[i*pri[j]]=1; if(i%pri[j]) ; else break; } } } ll phi(int n) { ll res=n; for(int i=1; i<=tot; i++) { if(n%pri[i]==0) { res=res/pri[i]*(pri[i]-1); while(n%pri[i]==0) { n/=pri[i]; } } if(n==1) return res; } if(n==1) return res; else { res=res/n*(n-1); return res; } } int t,n,m; int fac[100]; int pfac[100]; int ftop=0; void fj(int n) { ftop=0; for(int i=1; i<=tot; i++) { if(n%pri[i]==0) { fac[++ftop]=pri[i]; pfac[ftop]=0; while(n%pri[i]==0) { n/=pri[i]; pfac[ftop]++; } } } if(n!=1) { fac[++ftop]=n; pfac[ftop]=1; } return; } ll ans; int power(int p,int n) { if(n==0) return 1; int res=1; while(n--) res*=p; return res; } void dfs(int pos,int cur) { if(pos>ftop) { if(cur>=m) ans+=phi(n/cur); return; } for(int i=0; i<=pfac[pos]; i++) { dfs(pos+1,cur*power(fac[pos],i)); } } int main() { #ifdef Yinku freopen("Yinku.in","r",stdin); #endif // Yinku sieve(N); scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); ans=0; fj(n); dfs(1,1); printf("%I64d\n",ans); } }
T^TOJ - 1251 - ?????TMD - 歐拉函數 - 質因數分解