bzoj 2693 jzptab
原创
©著作权归作者所有:来自51CTO博客作者mb63eca9f086a52的原创作品,请联系作者获取转载授权,否则将追究法律责任
2693: jzptab
Time Limit: 10 Sec Memory Limit: 512 MB
Submit: 1451 Solved: 576
[Submit][Status][Discuss]
Description
Input
一个正整数T表示数据组数
接下来T行 每行两个正整数 表示N、M
Output
T行 每行一个整数 表示第i组数据的结果
Sample Input
1
4 5
Sample Output
122
HINT
T <= 10000
N, M<=10000000
【分析】
本来想做Crash的数字表格(此题的简化版本…),结果演了一会演到了这道题上…一看PoPoQQQ的题解诶怎么和我演的不一样…Orz
假设 n<=m
ans=∑ n i=1 ∑ m j=1 ijgcd(i,j)
=∑ n d=1 1d ∑ nd i=1 ∑ md j=1 (∑ p|gcd(i,j) μ(p))ij∗d 2
诶呀卧槽实在太难写了…纯粹浪费生命嘛,留个坑以后填(气死了)
【代码】
//bzoj 2693 jzptab
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 10000000
#define ll long long
#define M(a) memset(a,0,sizeof a)
#define fo(i,j,k) for(int i=j;i<=k;i++)
using namespace std;
const int p=100000009;
const int mxn=10000005;
bool vis[mxn];
int pri[mxn];
ll miu[mxn];
int T,n,m;
inline void shai()
{
miu[1]=1;
fo(i,2,N)
{
if(!vis[i]) pri[++pri[0]]=i,miu[i]=(i-(ll)i*i%p+p)%p;
for(int j=1;j<=pri[0]&&i*pri[j]<=N;j++)
{
vis[i*pri[j]]=1;
if(i%pri[j]==0)
{
miu[i*pri[j]]=miu[i]*pri[j]%p;
break;
}
miu[i*pri[j]]=miu[i]*miu[pri[j]]%p;
}
}
fo(i,1,N) miu[i]=(miu[i]+miu[i-1])%p;
}
inline ll calc(int x)
{
return (ll)x*(x+1)/2%p;
}
inline ll solve(int n,int m)
{
ll ans=0;
if(n>m) swap(n,m);
for(int i=1,last=0;i<=n;i=last+1)
{
last=min(n/(n/i),m/(m/i));
ans=(ans+(miu[last]-miu[i-1]+p)%p*calc(n/i)%p*calc(m/i)%p)%p;
}
return ans;
}
int main()
{
shai();
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
printf("%lld\n",solve(n,m));
}
return 0;
}