HDU 5528 Count a * b 2015 长春现场赛(积性函数)

来源:互联网 发布:新疆教师网络培训登录 编辑:程序博客网 时间:2024/06/16 18:10

题目链接

Count a * b

分析

这是很有意思的积性函数问题

反过来定义

h(m)=m2f(m)=a,b[ab%m=0]=a=1,bmgcd(a,m)|b=a=1mgcd(a,m)=d|mdϕ(m/d)

h(m) 是恒等映射与Euler函数的狄利克雷卷积,所以它是积性函数
对于素数p
h(pk)=ki=0piϕ(pki)=pk+k1i=0pi(pkipki1)=pk1(k(p1)+p)

所以

g(n)=d|nd2h(d)

分别求
g1(n)=d|nd2g2(n)=d|nh(d)

g1,g2均是1和积性函数的狄利克雷卷积,所以他们都是积性函数.以g2举例n=pr11prkk

g2(n)=i=1kg2(pri)=i=1k(j=0rih(pji))

AC code

//Problem : 5528 ( Count a * b )     Judge Status : Accepted//RunId : 22241701    Language : G++    Author : zouzhitao//Code Render Status : Rendered By HDOJ G++ Code Render Version 0.01 Beta#include<bits/stdc++.h>#define pb push_back#define mp make_pair#define PI acos(-1)#define fi first#define se second#define INF 0x3f3f3f3f#define INF64 0x3f3f3f3f3f3f3f3f#define random(a,b) ((a)+rand()%((b)-(a)+1))#define ms(x,v) memset((x),(v),sizeof(x))#define sci(x) scanf("%d",&x );#define scf(x) scanf("%lf",&x );#define eps 1e-8#define dcmp(x) (fabs(x) < eps? 0:((x) <0?-1:1))#define lc o<<1#define rc o<<1|1using namespace std;typedef unsigned long long ULL;typedef long long LL;typedef long double DB;typedef pair<int,int> Pair;const int maxn = 1e5+10;int prime[maxn],cnt;//void getPrime(/* arguments */) {    cnt =0;    ms(prime,0);    for(int i=2;  i<maxn ; ++i){        if(!prime[i]){prime[cnt++] = i;}        for(int j=0 ; j<cnt&&prime[j]*i < maxn ; ++j){            prime[i*prime[j]] =1;            if(i%prime[j]==0)break;        }    }}ULL power_mod(ULL x,ULL n){    ULL ret =1;    while (n) {        if(n&1)ret*=x;        n>>=1;        x=x*x;    }    return ret;}ULL H(ULL p,ULL k){    return k==0?1 :power_mod(p,k-1)*(k*(p-1)+p);}ULL SQRT(ULL p,ULL k){    return power_mod(p,2*k);}int main(){    // ios_base::sync_with_stdio(0);    // cin.tie(0);    // cout.tie(0);    int T;    getPrime();    scanf("%d",&T );    while (T--) {        int n;        cin>>n;        int nn = n;        ULL f1=1,f2=1;        for(int i=0 ; i<cnt && prime[i]*prime[i]<=nn; ++i){            if(n%prime[i]==0){                int k=0;                while (n%prime[i]==0) {                    n/=prime[i];k++;                }                ULL val1 = 0;                ULL val2 =0;                ULL p = prime[i];                for(int i=0 ; i<=k ;++i){                    val1 += H(p,i);val2 += SQRT(p,i);                }                f1 *=val1;                f2 *= val2;            }        }        if(n!=1){            f1 *= (H(n,0)+H(n,1));            f2 *= (SQRT(n,0)+SQRT(n,1));        }        std::cout << f2-f1 << '\n';    }    //std::cout << "time "<< clock()/1000 <<"ms"<< '\n';    return 0;}
原创粉丝点击