bzoj2705 [SDOI2012]Longge的問題——因數
阿新 • • 發佈:2018-06-24
div str 防止 blank mes i++ ret bzoj using
題目:https://www.lydsy.com/JudgeOnline/problem.php?id=2705
一開始自己想了半天...
有了點思路:遍歷 n 的因數 k,每個因數要預處理出 gcd 等於這個因數的數的個數 s[k];
預處理過程中還要去重:s[k] = (n-1) / k , s[k] -= s[2*k] + s[3*k] +......,&(*%$^&...
正要勇猛去寫的時候還是點開了TJ,然後被自己的愚蠢暴擊...
考慮 gcd ( n , m ) = k 的 m 的個數,發現 gcd ( n/k , m/k ) = 1,也就是 phi ( n/k )!!!
所以遍歷因數,求它們的歐拉函數;
但範圍太大了不能預處理,所以暴力每次求;
然而發現自己暴力也不會了,想了許多純純的暴力...
還是要用公式的啊... phi (x) = x * ∏ ( 1 - 1 / p[i] );
總之,就是一道關於歐拉函數的水題...
代碼如下:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; typedef long long ll; ll n,ans; ll phi(ll x) { ll ret=x;for(int i=2;i*i<=x;i++) if(x%i==0) { ret=ret/i*(i-1);//防止溢出 while(x%i==0)x/=i; } if(x>1) ret=ret/x*(x-1); return ret; } int main() { scanf("%lld",&n); for(int i=1;i*i<=n;i++) if(n%i==0) { ans+=i*phi(n/i);if(i*i<n) ans+=n/i*phi(i);//別算2遍 sqrt(n) } printf("%lld",ans); return 0; }
bzoj2705 [SDOI2012]Longge的問題——因數