HDU 5528
Marry likes to count the number of ways to choose two non-negative integers aa and bbless than mm to make a×ba×b mod m≠0m≠0.
Let’s denote f(m)f(m) as the number of ways to choose two non-negative integers aa and bbless than mm to make a×ba×b mod m≠0m≠0.
She has calculated a lot of f(m)f(m) for different mm, and now she is interested in another function g(n)=∑m|nf(m)g(n)=∑m|nf(m). For example, g(6)=f(1)+f(2)+f(3)+f(6)=0+1+4+21=26g(6)=f(1)+f(2)+f(3)+f(6)=0+1+4+21=26. She needs you to double check the answer.
Give you nn. Your task is to find g(n)g(n) modulo 264264.
Input
The first line contains an integer TT indicating the total number of test cases. Each test case is a line with a positive integer nn.
1≤T≤200001≤T≤20000
1≤n≤1091≤n≤109
Output
For each test case, print one integer ss, representing g(n)g(n) modulo 264264.
Sample Input
2
6
514
Sample Output
26
328194
思路
我们考虑 怎么计算 , 等于 减去是 的倍数的方案数
令 表示是 的倍数的方案数,则 如何理解呢?我们去枚举 的值,可知这个值会等于 的某个因子,因此我们枚举 的因子,则当 时,即 , 有 种取值,由于a只有 的因子d,则 要包含 这个因子,那么有多少 满足呢?即 个 。因此
所以所求为
对于第二项,质因子分解后,则
对于 的因子只有 个,即 级别,因此总共只有质因子分解的时间
总时间复杂度 注意这里质因子分解时用素数去筛(先预处理出素数) 否则
本题还有一种思路 我们知道 ,其卷积形式为 其中 为恒等1函数, 为单位函数。本题我们要求解的是
几个式子总结:
- 中任选两个数 ,且 是 的倍数的方案数
代码
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
bool valid[35000];
int ans[35000];
int tot=0;
void get_prime(int n)
{
tot=0;
memset(valid,true,sizeof(valid));
for(int i=2;i<=n;++i){
if(valid[i]){
ans[++tot]=i;
}
for(int j=1;j<=tot&&ans[j]*i<=n;++j){
valid[ans[j]*i]=false;
if(i%ans[j]==0) break;
}
}
}
int main()
{
//cout<<(1<<30)<<endl;
int t;
get_prime(35000);
//cout<<tot<<endl;
//cin>>t;
scanf("%d",&t);
while(t--)
{
//assert(t>15000);
ll n;
scanf("%lld",&n);
ll ans1=1;
ll ans2=1;
for(int i=1;ans[i]*ans[i]<=n;++i){
ll p[35];
if(n%ans[i]==0){
ll res=0;
ll res1=0;
res1+=1*1;
int k=0;p[0]=1;
while(n%ans[i]==0){
n/=ans[i];
k++;
p[k]=p[k-1]*ans[i];
res1+=(p[k]*p[k]);
}
//cout<<k<<endl;
ans1*=res1;
//assert(ans1<(1LL<<62));
for(int j=0;j<=k;++j){
for(int d=0;d<=j;++d){
if(j>d) res+=(p[j-d]-p[j-d-1])*p[d];
else res+=p[d];
}
}
ans2*=res;
}
}
if(n>1){
ans1*=(1+n*n);
ll res=0;
res+=n+n;
ans2*=res;
}
//ans2=0;
printf("%lld\n",ans1-ans2);
//cout<<ans1-ans2<<endl;
}
return 0;
}