首页 > 其他 > 详细

T^TOJ - 1251 - ?????TMD - 欧拉函数 - 质因数分解

时间:2019-05-16 18:35:13      阅读:178      评论:0      收藏:0      [点我收藏+]

http://www.fjutacm.com/Problem.jsp?pid=1251
想了很久,一开始居然还直接枚举因子d,计算重复了。

首先你要找与n的最大公因子大于m的x的个数。

\[\sum\limits_{x=1}^n [gcd(x,n)>=m]\]

不能直接枚举d,d必须是n的因子,否则与n的gcd都不可能是d。

\[\sum\limits_{d=m \& d|n}^n \sum\limits_{x=1}^n [gcd(x,n)==d]\]

后面那个有点眼熟?

\[\sum\limits_{d=m \& d|n}^n \sum\limits_{x=1}^{n/d} [gcd(x,n/d)==1]\]

果然是欧拉函数:

\[\sum\limits_{d=m \& d|n}^n \varphi(n/d)\]

然后,查了一下,因子的个数实在不会太多1e8不到1000个,1e17不到100000个。

那就直接质因数分解然后搜索。

一发AC。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=100000;

int pri[N+5],tot,zhi[N+5];
void sieve(int n) {
    zhi[1]=1;
    for(int i=2; i<=n; i++) {
        if(!zhi[i])
            pri[++tot]=i;
        for(int j=1; j<=tot&&i*pri[j]<=n; j++) {
            zhi[i*pri[j]]=1;
            if(i%pri[j])
                ;
            else
                break;
        }
    }
}

ll phi(int n) {
    ll res=n;
    for(int i=1; i<=tot; i++) {
        if(n%pri[i]==0) {
            res=res/pri[i]*(pri[i]-1);
            while(n%pri[i]==0) {
                n/=pri[i];
            }
        }
        if(n==1)
            return res;
    }
    if(n==1)
        return res;
    else {
        res=res/n*(n-1);
        return res;
    }
}

int t,n,m;

int fac[100];
int pfac[100];
int ftop=0;
void fj(int n) {
    ftop=0;
    for(int i=1; i<=tot; i++) {
        if(n%pri[i]==0) {
            fac[++ftop]=pri[i];
            pfac[ftop]=0;
            while(n%pri[i]==0) {
                n/=pri[i];
                pfac[ftop]++;
            }
        }
    }
    if(n!=1) {
        fac[++ftop]=n;
        pfac[ftop]=1;
    }
    return;
}

ll ans;

int power(int p,int n) {
    if(n==0)
        return 1;
    int res=1;
    while(n--)
        res*=p;
    return res;
}

void dfs(int pos,int cur) {
    if(pos>ftop) {
        if(cur>=m)
            ans+=phi(n/cur);
        return;
    }
    for(int i=0; i<=pfac[pos]; i++) {
        dfs(pos+1,cur*power(fac[pos],i));
    }
}

int main() {
#ifdef Yinku
    freopen("Yinku.in","r",stdin);
#endif // Yinku
    sieve(N);
    scanf("%d",&t);
    while(t--) {
        scanf("%d%d",&n,&m);
        ans=0;
        fj(n);
        dfs(1,1);
        printf("%I64d\n",ans);
    }
}

T^TOJ - 1251 - ?????TMD - 欧拉函数 - 质因数分解

原文:https://www.cnblogs.com/Yinku/p/10877188.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!