luogu P2568 GCD
阿新 • • 發佈:2018-08-03
ostream line gis const math lin 而不是 情況 include 貢獻為\(\phi[j]\)
所以洛谷兩道這樣的題,另一道要用MI?
考慮每個質數對答案的貢獻
如果有\(gcd(a,b)=p\),則顯然\(gcd(\frac{a}{p},\frac{b}{p})=1\)
所以每個\(p\)對答案的貢獻就是\(\sum_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{p}\rfloor}[gcd(i,j)=1]\)
若\(i>j\),對於每個\(i\),貢獻為\((\sum_{j=1}^{i-1}[gcd(i,j)=1])=\phi[i]\)
對於\(i<j\)的情況也是一樣的,也就是每個單獨的\(j\)
若\(i=j\),則有\(1\)的貢獻
最終答案即為\((\sum_{i=1}^{m}\sum_{j=1}^{\lfloor {n/p_i}\rfloor}\phi[j])+m(m\)為質數個數,\(p_i\)為第\(i\)個質數\()\)
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<vector> #include<cmath> #include<ctime> #include<queue> #include<map> #define LL long long #define il inline #define re register using namespace std; const LL mod=1000000007; il LL rd() { re LL x=0,w=1;re char ch; while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();} while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();} return x*w; } LL n,phi[10000010],ans; int prm[1000010],tt; char v[10000010]; il void init() { phi [1] = 1; for(re int i=2;i<=n;i++) { if(!v[i]) prm[++tt]=i,phi[i]=i-1; for(re int j=1;j<=tt&&i*prm[j]<=n;j++) { v[i*prm[j]]=1,phi[i*prm[j]]=phi[i]*(prm[j]-1); if(i%prm[j]==0) {phi[i*prm[j]]+=phi[i];break;} } } } il void work() { for(re int i=1;i<=n;i++) phi [i] + = phi [i-1]; for(re int i=1;i<=tt;i++) ans+=phi[n/prm[i]]; printf("%lld\n",(ans<<1)-tt); //知道為什麽是-而不是+嗎? 嘿嘿嘿 } int main() { n=rd(); init(); work(); return 0; }
luogu P2568 GCD