1. 程式人生 > >BZOJ 2820: YY的GCD [莫比烏斯反演]

BZOJ 2820: YY的GCD [莫比烏斯反演]

題解:

和上一題相同的函式:

  為滿足的對數

  為滿足的對數

顯然,反演後得到

 

可以列舉每一個質數,套用上一題的做法,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;
}