https://www.luogu.org/problemnew/show/P3455
就是https://www.cnblogs.com/hehe54321/p/9315244.html里面的方法2了,升级版的整除分块,可以两个变量一起搞
预处理莫比乌斯函数的前缀和之后就可以每次$O(sqrt{n}+sqrt{m})$回答
那篇题解里面用了一个技巧:${lfloor}frac{{lfloor}frac{a}{b}{ floor}}{c}{ floor}={lfloor}frac{a}{bc}{ floor}$
(当然a,b,c都为正整数)
证了好久。。。
这么证:
设${lfloor}frac{a}{bc}{ floor}=p$,则p为整数,且$p<=frac{a}{bc}<p+1$
则$pc<=frac{a}{b}<pc+c$
而$pc$与$pc+c$都为整数
因此$pc<={lfloor}frac{a}{b}{ floor}<pc+c$
所以$p<=frac{{lfloor}frac{a}{b}{ floor}}{c}<p+1$
所以${lfloor}frac{{lfloor}frac{a}{b}{ floor}}{c}{ floor}=p={lfloor}frac{a}{bc}{ floor}$
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<vector> 5 using namespace std; 6 #define fi first 7 #define se second 8 #define mp make_pair 9 #define pb push_back 10 typedef long long ll; 11 typedef unsigned long long ull; 12 typedef pair<int,int> pii; 13 #define N 50100 14 ll prime[N+100],len,mu[N+100],dd[N+100]; 15 bool nprime[N+100]; 16 ll a,c,n,m,k,ans,ed; 17 int main() 18 { 19 ll i,j,T,TT; 20 mu[1]=1; 21 for(i=2;i<=N;i++) 22 { 23 if(!nprime[i]) prime[++len]=i,mu[i]=-1; 24 for(j=1;j<=len&&i*prime[j]<=N;j++) 25 { 26 nprime[i*prime[j]]=1; 27 if(i%prime[j]==0) {mu[i*prime[j]]=0;break;} 28 else mu[i*prime[j]]=-mu[i]; 29 } 30 } 31 for(i=1;i<=N;i++) dd[i]=dd[i-1]+mu[i]; 32 scanf("%lld",&T); 33 for(TT=1;TT<=T;TT++) 34 { 35 scanf("%lld%lld%lld",&n,&m,&k);n/=k;m/=k; 36 ans=0; 37 if(n>m) swap(n,m); 38 for(i=1;i<=n;i=j+1) 39 { 40 j=min(n,min(n/(n/i),m/(m/i))); 41 ans+=(dd[j]-dd[i-1])*(n/i)*(m/i); 42 } 43 printf("%lld ",ans); 44 } 45 return 0; 46 }
https://www.luogu.org/problemnew/show/P2522
https://www.lydsy.com/JudgeOnline/problem.php?id=2301
这题基本一样的,就是加个容斥。。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<vector> 5 using namespace std; 6 #define fi first 7 #define se second 8 #define mp make_pair 9 #define pb push_back 10 typedef long long ll; 11 typedef unsigned long long ull; 12 typedef pair<int,int> pii; 13 #define N 50100 14 ll prime[N+100],len,mu[N+100],dd[N+100]; 15 bool nprime[N+100]; 16 ll a,c,n,m,k; 17 ll calc(ll n,ll m) 18 { 19 if(n==0||m==0) return 0; 20 ll ans=0; 21 if(n>m) swap(n,m); 22 n/=k;m/=k; 23 for(ll i=1,j;i<=n;i=j+1) 24 { 25 j=min(n,min(n/(n/i),m/(m/i))); 26 ans+=(dd[j]-dd[i-1])*(n/i)*(m/i); 27 } 28 return ans; 29 } 30 int main() 31 { 32 ll i,j,T,TT; 33 mu[1]=1; 34 for(i=2;i<=N;i++) 35 { 36 if(!nprime[i]) prime[++len]=i,mu[i]=-1; 37 for(j=1;j<=len&&i*prime[j]<=N;j++) 38 { 39 nprime[i*prime[j]]=1; 40 if(i%prime[j]==0) {mu[i*prime[j]]=0;break;} 41 else mu[i*prime[j]]=-mu[i]; 42 } 43 } 44 for(i=1;i<=N;i++) dd[i]=dd[i-1]+mu[i]; 45 scanf("%lld",&T); 46 for(TT=1;TT<=T;TT++) 47 { 48 scanf("%lld%lld%lld%lld%lld",&a,&n,&c,&m,&k); 49 printf("%lld ",calc(n,m)-calc(a-1,m)-calc(n,c-1)+calc(a-1,c-1)); 50 } 51 return 0; 52 }