[2020.12.07週一]賽氪A題
阿新 • • 發佈:2020-12-09
題解:根據歐幾里得輾轉相除,很容易想到\(gcd(i,n-i)=gcd(i,n)\)
\[\begin{align*} &當n>1,f(n)=\sum_{i=1}^{n-1}[gcd(i,n-i)==1]=\sum_{i=1}^{n-1}[gcd(i,n)==1]+[gcd(n,n)==0]=\sum_{i=1}^{n}[gcd(i,n)==1]=\varphi (n)\\ &\therefore f(n)=\varphi(n)\\ &g(n)=\sum_{d|n}f(\frac{n}{d})=\sum_{d|n}f(\frac{n}{d})·1(d)=\varphi*1=id,恆等函式\\ &\therefore g(n)=n\\ &綜上,這題只要作(k+1)/2次尤拉就好了;\\ &但這個k依然很大,但沒關係因為log次必然迭代到1,按照cy的說法是暴跳到1然後break;\\ &複雜度O(n\log n)\\ &下面來證明[思路by cy]:log次必然迭代到1(賽場上因為沒證出來,不敢衝)\\ &根據尤拉定理,n=p_1^{k_1}p_2^{k_2}\cdots p_n^{k_n}\\ &\varphi(奇數)=偶數\\ &\varphi(偶數)\le偶數/2\\ &\varphi(n)\le n-1\\ &因此,\varphi(\varphi(n))\le n/2 \end{align*} \]#include<bits/stdc++.h> using namespace std; typedef long long ll; const int mod=1e9+7; long long euler(long long n) { long long res=n,a=n; for(long long i=2;i*i<=a;i++){ if(a%i==0){ res=res/i*(i-1);//先進行除法是為了防止中間資料的溢位 while(a%i==0) a/=i; } } if(a>1) res=res/a*(a-1); return res;//返回euler(n) } int main() { int T;ll n, k; scanf("%d",&T); while(T--) { scanf("%lld%lld",&n,&k); k=(k+1)/2; for(int i=1;i<=k;i++){ n=euler(n); if(n==1) break; } printf("%lld\n",n%mod); } }