[HAOI2011]Problem b [Mobius]
阿新 • • 發佈:2018-11-10
題意:
對於給出的n個詢問,每次求有多少個數對(x,y),滿足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函式為x和y的最大公約數。
100%的資料滿足:1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000
思路:
是之前做的求(1,n),(1,m)求gcd==k 這題的擴充套件版本,加個容斥
其中(1,a),(1,b)求gcd==k
複雜度
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=5e5+5; const int MOD=1e9+7; int a,b,c,d,k; template <class T> bool sf(T &ret){ //Faster Input char c; int sgn; T bit=0.1; if(c=getchar(),c==EOF) return 0; while(c!='-'&&c!='.'&&(c<'0'||c>'9')) c=getchar(); sgn=(c=='-')?-1:1; ret=(c=='-')?0:(c-'0'); while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0'); if(c==' '||c=='\n'){ ret*=sgn; return 1; } while(c=getchar(),c>='0'&&c<='9') ret+=(c-'0')*bit,bit/=10; ret*=sgn; return 1; } int mu[N], vis[N], prime[N]; ll summu[N]; int tot;//用來記錄prime的個數 void init(){ mu[1] = 1; for(int i = 2; i < N; i ++){ if(!vis[i]){ prime[tot ++] = i; mu[i] = -1; } for(int j = 0; j < tot && i * prime[j] < N; j ++){ vis[i * prime[j]] = 1; if(i % prime[j]) mu[i * prime[j]] = -mu[i]; else{ mu[i * prime[j]] = 0; break; } } } for(int i=1;i<N;i++) summu[i]=mu[i]+summu[i-1]; } ll f(int n,int m){ ll ans=0; n/=k,m/=k; int mn=min(n,m); for(int d=1;d<=mn;++d){ // ans+=mu[d]*(n/d)*(m/d); ll ed=min(n/(n/d),m/(m/d)); ans+=(summu[ed]-summu[d-1])*(n/d)*(m/d); d=ed; } return ans; } int main(void){ init(); int q; sf(q); while(q--){ sf(a);sf(b);sf(c);sf(d);sf(k); ll ans=f(b,d)-f(a-1,d)-f(c-1,b)+f(a-1,c-1); printf("%lld\n",ans); } return 0; }