Count a * b
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 262 Accepted Submission(s): 132
Problem Description
Marry likes to count the number of ways to choose two non-negative integers
a
and
b
less than
m
to make
a×b
mod
m≠0
.
Let's denote f(m) as the number of ways to choose two non-negative integers a and b less than m to make a×b mod m≠0 .
She has calculated a lot of f(m) for different m , and now she is interested in another function g(n)=∑m|nf(m) . For example, g(6)=f(1)+f(2)+f(3)+f(6)=0+1+4+21=26 . She needs you to double check the answer.
Give you n . Your task is to find g(n) modulo 264 .
Let's denote f(m) as the number of ways to choose two non-negative integers a and b less than m to make a×b mod m≠0 .
She has calculated a lot of f(m) for different m , and now she is interested in another function g(n)=∑m|nf(m) . For example, g(6)=f(1)+f(2)+f(3)+f(6)=0+1+4+21=26 . She needs you to double check the answer.
Give you n . Your task is to find g(n) modulo 264 .
Input
The first line contains an integer
T
indicating the total number of test cases. Each test case is a line with a positive integer
n
.
1≤T≤20000
1≤n≤109
1≤T≤20000
1≤n≤109
Output
For each test case, print one integer
s
, representing
g(n)
modulo
264
.
Sample Input
2 6 514
Sample Output
26 328194
Source
#include<bits/stdc++.h>
const int maxn=100001;
using namespace std;
bool bb[maxn];
int prim[maxn],tot,v[maxn],s[maxn],t[maxn],n;
void prepare(){
bb[1]=1;v[1]=1;t[1]=1;
for(int i=2;i<=maxn;i++){
if(!bb[i]){
prim[++tot]=i;
v[i]=2*i-1;
s[i]=1;
t[i]=i;
}
for(int j=1;j<=tot&&prim[j]*i<maxn;j++){
int z=prim[j]*i;
bb[z]=true;
if(i%prim[j]==0){
s[z]=s[i]+1;
t[z]=t[i]+prim[j];
v[z]=v[i/t[i]]*t[i]*(prim[j]*z-z+prim[j]);
break;
}
v[z]=v[prim[j]]*v[i];
s[z]=1;
t[z]=prim[j];
}
}
}
void work(){
scanf("%d",&n);
unsigned long long ans1=1,ans2=1;
//printf("%d\n",prim[1]);
for(int i=1;i<=tot&&1LL*prim[i]*prim[i]<=n;i++){
if(n%prim[i])continue;
unsigned long long tmp=0,tmp2=1;
unsigned long long k1=1,k2=1;
do{
tmp++;
tmp2*=prim[i];
k1+=tmp2*tmp2;
k2+=tmp2/prim[i]*(1LLU*prim[i]*tmp-tmp+prim[i]);
n/=prim[i];
}while(n%prim[i]==0);
//printf("%d %I64u %I64u %d %d %I64u %I64u\n",i,tmp,tmp2,prim[i],n,k1,k2);
ans1*=k1;ans2*=k2;
}
if(n>1){
ans1*=(1LLU*n*n+1);
ans2*=2*n;
}
//cout<<ans1<<" "<<ans2<<endl;
printf("%llu\n",ans1-ans2);
}
int main(){
prepare();
int t;scanf("%d",&t);
while(t--)work();
return 0;
}