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

题目链接

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
#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|1
using 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;  iif(!prime[i]){prime[cnt++] = i;}
        for(int j=0 ; j1;
            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 ; iif(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;
}

你可能感兴趣的:(算法刷题)