1. 程式人生 > >hdu 1695 GCD(莫比烏斯入門)

hdu 1695 GCD(莫比烏斯入門)

技術分享 sin urn cas str 由於 ons pre ()

題意:求a<=x<=b ,x<=y<=d,中gcd(x,y)==k的數對個數

思路:題目可以轉化成求1<=x<=b/k,1<=y<=d/k中gcd(x,y)=1的數對的個數

我們設f(d)表示恰好gcd(x,y)==d的個數,F(d)表示gcd為d的倍數的數對個數

F(n)=∑d|nf(d)=> f(d)=∑d|nu(d)F(n/d)

令p=b/k q=d/k

F(d)的計算十分簡單 floor(p/d)*floor(q/d)

再利用線性篩法求莫比烏斯即可

由於題目要求(1,2)和(2,1)是一樣的,所以要去掉重復的(來源見水印)

技術分享

代碼:

#include <iostream>
#include <cstring>
#define ll long long

using namespace std;

const int maxn=100005;
bool check[maxn+10];
int prime[maxn+10],mu[maxn+10],sum[maxn+10];

void Mublus()
{
    memset(check,false,sizeof(check));
    mu[
1]=1; int tot=0; for(int i=2;i<=maxn;i++) { if(check[i]==false) { prime[tot++]=i; mu[i]=-1; } for(int j=0;j<tot;j++) { if(i*prime[j]>maxn) break; check[i*prime[j]]=true; if(i%prime[j]==0
) { mu[i*prime[j]]=0; break; } else { mu[i*prime[j]]=-mu[i]; } } } } int main() { int t,cas=1; Mublus(); cin>>t; while(t--) { int a,b,c,d,k; cin>>a>>b>>c>>d>>k; cout<<"Case "<<cas++<<": "; if(k==0) { cout<<"0"<<endl; continue; } b=b/k; d=d/k; if(b>d) swap(b,d); ll ans,rep; ans=0; rep=0; for(int i=1;i<=b;i++) { ans+=(ll)mu[i]*(b/i)*(d/i); rep+=(ll)mu[i]*(b/i)*(b/i); } ans=ans-rep/2; cout<<ans<<endl; } return 0; }

hdu 1695 GCD(莫比烏斯入門)