您的位置:首页 > 其它

bzoj3994【SDOI2005】约数个数和

2016-04-05 23:55 295 查看

3994: [SDOI2015]约数个数和

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 527  Solved: 344

[Submit][Status][Discuss]

Description

 设d(x)为x的约数个数,给定N、M,求  


Input

输入文件包含多组测试数据。

第一行,一个整数T,表示测试数据的组数。
接下来的T行,每行两个整数N、M。

Output

 T行,每行一个整数,表示你所求的答案。

Sample Input

2

7 4

5 6

Sample Output

110

121

HINT

 1<=N, M<=50000

1<=T<=50000

Source

Round 1 感谢yts1999上传

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 50000
using namespace std;
int t,n,m,tot;
int mu[maxn+5],pri[maxn+5],cnt[maxn+5],d[maxn+5];
bool mark[maxn+5];
inline int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline void pre()
{
mu[1]=1;d[1]=1;
F(i,2,maxn)
{
if (!mark[i]){pri[++tot]=i;mu[i]=-1;d[i]=2;cnt[i]=1;}
for(int j=1;j<=maxn&&pri[j]*i<=maxn;j++)
{
mark[pri[j]*i]=true;
if (i%pri[j]==0)
{
mu[i*pri[j]]=0;
d[i*pri[j]]=d[i]/(cnt[i]+1)*(cnt[i]+2);
cnt[i*pri[j]]=cnt[i]+1;
break;
}
mu[i*pri[j]]=-mu[i];
d[i*pri[j]]=d[i]*2;
cnt[i*pri[j]]=1;
}
}
F(i,1,maxn) mu[i]+=mu[i-1],d[i]+=d[i-1];
}
int main()
{
pre();
t=read();
while (t--)
{
n=read();m=read();
if (n>m) swap(n,m);
ll ans=0;
for(int i=1,pos;i<=n;i=pos+1)
{
pos=min(n/(n/i),m/(m/i));
ans+=(ll)(mu[pos]-mu[i-1])*d[n/i]*d[m/i];
}
printf("%lld\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: