http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=21352
∑i=1a∑j=1bgcd(i,j)==d=∑i=1a/d∑j=1b/dgcd(i,j)==1=∑i=1a/d∑j=1b/d∑d|i,d|jmin(i,j)μ(d)=∑d1=1min(a/d,b/d)μ(d1)∗(a/d/d1)∗(b/d/d1)
这题还要去一下重
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=1e5+100;
typedef __int64 LL;
int pri[N],pn,mu[N],p[N];
void init(){
mu[1]=1;
memset(p,0,sizeof(p));
int n=100000;
pn=0;
for(int i=2;i<=n;i++){
if(!p[i]){
pri[pn++]=i;
mu[i]=-1;
}
for(int j=0;j<pn;j++){
if((LL)i*pri[j]>n)break;
p[i*pri[j]]=1;
if(i%pri[j]==0){
mu[i*pri[j]]=0;break;
}
else {
mu[i*pri[j]]=-mu[i];
}
}
}
// for(int i=1;i<=10;i++){
// printf("%d %d %d\n",i,p[i],mu[i]);
// }
for(int i=1;i<=n;i++){
mu[i]+=mu[i-1];
}
}
LL f(int k1,int k2){
if(k1>k2)swap(k1,k2);
return (LL)(k2-k1)*k1+(LL)(k1-1)*k1/2+k1;
}
int main(){
#ifdef DouBi
freopen("in.cpp","r",stdin);
#endif // DouBi
int a,b,c,d,k;
init();
int cas=0;
int T;scanf("%d",&T);
while(T--){
scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
if(k==0){
printf("Case %d: 0\n",++cas);
continue;
}
b/=k;d/=k;
//printf("%d %d\n",b,d);
int r=min(b,d);
LL ans=0;
while(r>0){
//printf("%d ",r);
int k1=b/r;
int k2=d/r;
int l1=b/(k1+1)+1;
int l2=d/(k2+1)+1;
int l=max(l1,l2);
ans+=(LL)f(k1,k2)*(mu[r]-mu[l-1]);
//printf("%d %d %I64d\n",l,r,ans);
r=l-1;
}
printf("Case %d: %I64d\n",++cas,ans);
}
return 0;
}
本文介绍了一种基于数论的算法实现,通过计算特定条件下两个数的所有公约数中等于某个给定值的数量来解决问题。利用莫比乌斯函数进行优化,并提供了一个C++示例程序。
1万+

被折叠的 条评论
为什么被折叠?



