SPOJ 26108 TRENDGCD - Trending GCD

Discription

Problem statement is simple. Given and you need to calculate S(A,B) .

sigma(a=1 to A)sigma(b=1 to B) (a*b*f(gcd(a,b)))

Here, f(n)=n, if n is square free otherwise 0. Also f(1)=1.

Input

The first line contains one integer T - denoting the number of test cases.

lines follow each containing two integers A,B.

Output

For each testcase output the value of S(A,B) mod 1000000007 in a single line.

Constraints

  • T <= 1000
  • 1 <= A,B <= 1000000

Example

Input:
3
42 18
35 1
20 25

Output:
306395
630
128819


提一波公因数,把f(x) 化成 μ^2(x) * x,再化简之后发现需要筛一个积性函数(推一推就好了),然后分块回答询问即可。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1000000;
const int ha=1000000007;
int G[maxn+5],t,zs[maxn/5],T,n,m,low[maxn+5];
bool v[maxn+5];

inline int add(int x,int y){
	x+=y;
	return x>=ha?x-ha:x;
}

inline void init(){
    G[1]=low[1]=1;
	for(int i=2;i<=maxn;i++){
		if(!v[i]) zs[++t]=i,G[i]=i-1,low[i]=i;
		for(int j=1,u;j<=t&&(u=zs[j]*i)<=maxn;j++){
			v[u]=1;
			if(!(i%zs[j])){
				low[u]=low[i]*zs[j];
				if(v[low[i]]) G[u]=0;
				else G[u]=G[i/low[i]]*(ll)(ha-zs[j])%ha;
				break;
			}
			low[u]=zs[j],G[u]=G[i]*(ll)G[zs[j]]%ha;
		}
	}
	
	for(int i=1;i<=maxn;i++) G[i]=add(G[i-1],G[i]*(ll)i%ha*(ll)i%ha);
}

inline int C(int x){
	return (x*(ll)(x+1)>>1)%ha;
}

inline int solve(int x,int y){
	int ans=0;
	for(int i=1,j,nx,ny;i<=x;i=j+1){
		nx=x/i,ny=y/i,j=min(x/nx,y/ny);
		ans=add(ans,C(nx)*(ll)C(ny)%ha*(ll)add(G[j],ha-G[i-1])%ha);
	}
	return ans;
}

int main(){
	init();
	scanf("%d",&T);
	while(T--){
		scanf("%d%d",&n,&m);
		if(n>m) swap(n,m);
		printf("%d\n",solve(n,m));
	}
	
	return 0;
}

  

 
posted @ 2018-04-12 16:45  蒟蒻JHY  阅读(204)  评论(0编辑  收藏  举报