SPOJ 26108 TRENDGCD - Trending GCD
Discription
Problem statement is simple. Given A and B you need to calculate S(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.
T 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; }
我爱学习,学习使我快乐