【BZOJ3309】DZY Loves Math 解題報告
【BZOJ3309】DZY Loves Math
Description
對於正整數\(n\),定義\(f(n)\)為\(n\)所含質因子的最大冪指數。例如\(f(1960)=f(2^3×5^1×7^2)=3\),\(f(10007)=1\),\(f(1)=0\)。
給定正整數\(a,b\),求\(\sum\limits_{a_i=1}\sum\limits_{b_j=1}f(\gcd(i,j))\)。
Input
第一行一個數\(T\),表示詢問數。
接下來\(T\)行,每行兩個數\(a,b\),表示一個詢問。
Output
對於每一個詢問,輸出一行一個非負整數作為回答。
HINT
\(T≤10000\)
\(1≤a,b≤10^7\)
推式子可以得到
\[\sum_{T=1}^{\min(a,b)}\lfloor\frac{a}{T}\rfloor\lfloor\frac{b}{T}\rfloor\sum_{d|T}f(d)\mu(\frac{T}{d})\]
設\(g(T)=\sum_{d|T}f(d)\mu(\frac{T}{d})\),想一下卷積發現沒啥用,然後我就放棄了。
浪費了一次打表的大好機會...打表可以發現\(g\)只有\(01\)兩種值,但是沒什麽顯然的性質,於是我們可以暴力按意義分類討論取\(0\)或者\(1\)
然後我們討論一下,設\(p\)代表質數
\(g(p)=1\)
然後在計算式中令\(\frac{T}{d}\)
這樣的話可以發現\(f(d)\)只有兩種取值\(f(T)\)與\(f(T-1)\),暴力討論這兩種取值。
可以得到式子\(g(T)=-\sum_{d|x\&\&f(d)\not=f(x)}\mu(\frac{x}{d})\)
然後繼續討論可能取的\(01\)情況,發現如果冪全相等,可以取\((-1)^{k+1}\),\(k\)為約數個數
否則就取\(0\)
線篩的時候維護一下最小質因子的冪數和最小質因子的冪
Code:
#include <cstdio> #include <algorithm> #define ll long long const int N=1e7; using std::min; int pri[N+10],ispri[N+10],a[N+10],b[N+10],cnt; ll f[N+10],ans,n,m; void init() { for(int i=2;i<=N;i++) { if(!ispri[i]) { b[i]=pri[++cnt]=i; f[i]=a[i]=1; } for(int j=1;j<=cnt&&i*pri[j]<=N;j++) { ispri[i*pri[j]]=1; if(i%pri[j]==0) { a[i*pri[j]]=a[i]+1; b[i*pri[j]]=b[i]*pri[j]; if(i==b[i]) f[i*pri[j]]=1; else f[i*pri[j]]=a[i/b[i]]==a[i]+1?-f[i/b[i]]:0; break; } else { a[i*pri[j]]=1,b[i*pri[j]]=pri[j]; f[i*pri[j]]=a[i]==1?-f[i]:0; } } } for(int i=1;i<=N;i++) f[i]+=f[i-1]; } int main() { init();int T;scanf("%d",&T); while(T--) { ans=0; scanf("%lld%lld",&n,&m); for(ll l=1,r;l<=min(n,m);l=r+1) { r=min(n/(n/l),(m/(m/l))); ans+=(n/l)*(m/l)*(f[r]-f[l-1]); } printf("%lld\n",ans); } return 0; }
2018.12.15
【BZOJ3309】DZY Loves Math 解題報告