BZOJ 2820: YY的GCD [莫比烏斯反演]
阿新 • • 發佈:2018-11-13
題解:
和上一題相同的函式:
為滿足且和的的對數
為滿足且和的的對數
顯然,反演後得到
可以列舉每一個質數,套用上一題的做法,p相當於k,d*p也就是p的倍數了...很像上一題我WT1中的式子
其實d只要列舉到min(n,m)/p
然而複雜度承受不了,大約n/logn*sqrt(n)
我們設,那麼繼續得到
注意:之前有人跟我說ll和int速度差不多。。事實並不如此
所以能不用ll的地方還是不要用 避免被卡常
#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int n,m;
#define INF 3e8
const int maxn=1e7+100;
const int N=1e6+100;
int miu[maxn],sum[maxn],prime[N],pnum,ans,T;
int main()
{
freopen("noip.in","r",stdin);
freopen("noip.out","w",stdout);
cin>>T;
miu[1]=1;
for (int i=2;i<maxn;i++) miu[i]=-INF;
for (int i=2;i<maxn;i++)
{
if (miu[i]==-INF)
{
miu[i]=-1;
prime[++pnum]=i;
}
for (int j=1;j<=pnum;j++)
{
if (i*prime[j]>=maxn) break;
if (i%prime[j]==0) miu[i*prime[j]]=0;
else miu[i*prime[j]]=-miu[i];
}
}
for (int i=1;i<=pnum;i++)
for (int j=1;j<=(maxn-10)/prime[i];j++)
sum[j*prime[i]]+=miu[j];
for (int i=1;i<=maxn-10;i++) sum[i]+=sum[i-1];
while (T--)
{
cin>>n>>m;
if (n>m) swap(n,m);
ll ans=0;int j;
for (int i=1;i<=n;i=j+1)
{
j=min(n/(n/i),m/(m/i));
ans+=1ll*(n/i)*(m/i)*(sum[j]-sum[i-1]);
}
cout<<ans<<endl;
}
return 0;
}
#updata 18.11
#include <bits/stdc++.h> using namespace std; #define rint register ll #define IL inline #define rep(i,h,t) for (ll i=h;i<=t;i++) #define dep(i,t,h) for (ll i=t;i>=h;i--) #define ll long long const ll N=1e7+1; const ll M=N+1e4; ll mu[M],cnt,p[M]; ll ans[N]; bool pd[M]; int main() { ios::sync_with_stdio(false); ll T; cin>>T; pd[1]=1; mu[1]=1; rep(i,2,N) { if (!pd[i]) p[++cnt]=i,mu[i]=-1; for (ll j=1;j<=cnt&&p[j]*i<=N;j++) { pd[p[j]*i]=1; if (i%p[j]==0) break; else mu[i*p[j]]=-mu[i]; } } rep(i,2,N) if (!pd[i]) for (ll j=1;i*j<=N;j++) ans[i*j]+=mu[j]; rep(i,1,N) ans[i]+=ans[i-1]; rep(ttt,1,T) { ll n,m; cin>>n>>m; ll i=1; ll ans2=0; while (i<=n&&i<=m) { ll x1=n/(n/i),x2=m/(m/i); if (x1<=x2) { ans2+=(n/i)*(m/i)*(ans[x1]-ans[i-1]); i=x1+1; } else { ans2+=(n/i)*(m/i)*(ans[x2]-ans[i-1]); i=x2+1; } } cout<<ans2<<endl; } return 0; }