1. 程式人生 > >bzoj 3309 DZY Loves Math —— 莫比烏斯反演+數論分塊

bzoj 3309 DZY Loves Math —— 莫比烏斯反演+數論分塊

style std swa swap ont amp getchar() mes 分塊

題目:https://www.lydsy.com/JudgeOnline/problem.php?id=3309

憑著上課所講和與 Narh 討論推出式子來;

竟然是第一次寫數論分塊!所以迷惑了半天;

在預處理的篩中也犯了愚蠢的錯誤...總之全仰仗 Narh 提點了...

所以具體題解就看這裏咯:https://www.cnblogs.com/Narh/p/9740786.html

代碼如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace
std; typedef long long ll; int const xn=1e7+5; int T,a[xn],b[xn],c[xn],tot,pri[xn],cnt; ll s[xn]; bool vis[xn]; int rd() { int ret=0,f=1; char ch=getchar(); while(ch<0||ch>9){if(ch==-)f=0; ch=getchar();} while(ch>=0&&ch<=9)ret=(ret<<3)+(ret<<1)+ch-0,ch=getchar();
return f?ret:-ret; } void init() { int mx=1e7; for(int i=2;i<=mx;i++) { if(!vis[i])a[i]=b[i]=c[i]=1,pri[++cnt]=i; if(a[i]==1)s[i]=s[i-1]+((c[i]&1)?1:-1); else s[i]=s[i-1]; for(int j=1,k;j<=cnt&&(ll)i*pri[j]<=mx;j++) { vis[k=i*pri[j]]=1;
if(i%pri[j])//新增pri[j] { if(!a[i]||(a[i]&&b[i]!=1))a[k]=0,b[k]=0; else a[k]=1,b[k]=1; c[k]=c[i]+1; } else { int w=k,t=0; while(w%pri[j]==0)w/=pri[j],t++; if(w==1||(a[w]&&b[w]==t))a[k]=1,b[k]=t; else a[k]=0,b[k]=0; c[k]=c[i]; } } } } int main() { T=rd(); init(); while(T--) { int n,m; n=rd(); m=rd(); ll ans=0; if(n>m)swap(n,m); for(int i=1,nxt;i<=n;i=nxt+1) ans+=(ll)(n/i)*(m/i)*(s[nxt=min(n/(n/i),m/(m/i))]-s[i-1]); printf("%lld\n",ans); } return 0; }

bzoj 3309 DZY Loves Math —— 莫比烏斯反演+數論分塊