HDU5528 积性函数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Feynman1999/article/details/82421202

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.

img

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

思路

我们考虑 f ( n ) 怎么计算 , f ( n ) 等于 n 2 减去是 n 的倍数的方案数

h ( n ) 表示是 n 的倍数的方案数,则 h ( n ) = d | n φ ( n d ) d 如何理解呢?我们去枚举 g c d ( a , N ) 的值,可知这个值会等于 N 的某个因子,因此我们枚举 n 的因子,则当 g c d ( a , N ) = d 时,即 g c d ( a d , N d ) = 1 a φ ( N d ) 种取值,由于a只有 N 的因子d,则 b 要包含 N / d 这个因子,那么有多少 b 满足呢?即 N / N / d = d 个 。因此 h ( n ) = d | n φ ( n d ) d

所以所求为 g ( n ) = d | n f ( d ) = d | n d 2 d | n h ( d )

对于第二项,质因子分解后,则 d | p k h ( d ) = d | p k d | d φ ( d d ) d

对于 p k 的因子只有 k + 1 个,即 l o g 级别,因此总共只有质因子分解的时间

总时间复杂度 O ( T ( n l o g ( n ) + l o g 2 n ) ) 注意这里质因子分解时用素数去筛(先预处理出素数) 否则 T L E

本题还有一种思路 我们知道 d | n φ ( d ) = n ,其卷积形式为 φ I = I φ = i d 其中 I 为恒等1函数, i d 为单位函数。本题我们要求解的是 d | n h ( n ) = d | n w | d φ ( d w ) w = d | n ( φ i d ) ( d ) = I φ i d = ( I φ ) i d = i d i d = d | n i d ( d ) i d ( n d ) = d | n d n d = d | n n = n d | n 1 = n ( n )

几个式子总结:

  • d | n φ ( d ) = n
  • d | n φ ( n d ) d = g c d ( i , n ) ( 1 <= i <= n ) = [ 0 , n ) 中任选两个数 a , b ,且 a b n 的倍数的方案数
  • d | n w | d φ ( d w ) w = n ( n )

代码

#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;
}

猜你喜欢

转载自blog.csdn.net/Feynman1999/article/details/82421202