中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java怎么解決歐拉函數和莫比烏斯反演問題

發布時間:2022-04-06 16:43:11 來源:億速云 閱讀:148 作者:iii 欄目:編程語言

本文小編為大家詳細介紹“java怎么解決歐拉函數和莫比烏斯反演問題”,內容詳細,步驟清晰,細節處理妥當,希望這篇“java怎么解決歐拉函數和莫比烏斯反演問題”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。

題意:給定a,b,c,d,k

            x屬于[1 , c],y屬于[1 , d],求滿足gcd(x,y)=k的對數。其中<x,y>和<y,x>算相同。

解法一:不妨設c<d,x<=y。問題可以轉化為x屬于[1,c / k ],y屬于[1,d/k ],x和y互質的對數。

            那么假如y<=c/k,那么對數就是y從1到c/k歐拉函數的和。如果y>c/k,就只能從[ c/k+1 , d ]枚舉,然后利用容斥。詳見代碼:

/*********************************************************
  file name: hdu1695.cpp
  author : kereo
  create time:  2015年02月11日 星期三 18時08分43秒
*********************************************************/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<cmath>
#include<string>
#include<algorithm>
using namespace std;
typedef long long ll;
const int sigma_size=26;
const int N=100+50;
const int MAXN=100000+50;
const int inf=0x3fffffff;
const double eps=1e-8;
const int mod=1000000000+7;
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define PII pair<int, int>
#define mk(x,y) make_pair((x),(y))
int primecnt,factcnt;
int prime[MAXN],euler[MAXN],factor[N][2];
void getprime(){
    primecnt=0;
    memset(prime,0,sizeof(prime));
    for(int i=2;i<MAXN;i++){
        if(!prime[i])
            prime[primecnt++]=i;
        for(int j=0;j<primecnt && prime[j]<=MAXN/i;j++){
            prime[prime[j]*i]=1;
            if(i%prime[j] == 0)
                break;
        }
    }
}
void geteuler(){
    memset(euler,0,sizeof(euler));
    euler[1]=1;
    for(int i=2;i<MAXN;i++){
        if(!euler[i]){
            for(int j=i;j<MAXN;j+=i){
                if(!euler[j])
                    euler[j]=j;
                euler[j]=euler[j]/i*(i-1);
            }
        }
    }
}
int getfactor(int x){
    factcnt=0;
    for(int i=0;prime[i]<=x/prime[i];i++){
        factor[factcnt][1]=0;
        if(x%prime[i] == 0){
            factor[factcnt][0]=prime[i];
            while(x%prime[i] == 0){
                x/=prime[i];
                factor[factcnt][1]++;
            }
            factcnt++;
        }
    }
    if(x!=1){
        factor[factcnt][0]=x;
        factor[factcnt++][1]++;
    }
    return factcnt;
}
int solve(int n,int m){
    int ans=0;
    getfactor(m);
    for(int i=1;i<(1<<factcnt);i++){
        int cnt=0,res=1;
        for(int j=0;j<factcnt;j++){
            if(i&(1<<j)){
                cnt++;
                res*=factor[j][0];
            }
        }
        if(cnt & 1)
            ans+=n/res;
        else 
            ans-=n/res;
    }
    return n-ans;
}
int main(){
    int T,kase=0;
    scanf("%d",&T);
    getprime();
    geteuler();
    while(T--){
        printf("Case %d: ",++kase);
        int a,b,c,d,k;
        scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
        if(k == 0 || k>b || k>d){
            printf("0\n");
            continue;
        }
        if(b>d)
            swap(b,d);
        b/=k; d/=k;
        ll ans=0;
        for(int i=1;i<=b;i++)
            ans+=euler[i];
        for(int i=b+1;i<=d;i++)
            ans+=solve(b,i);
        printf("%I64d\n",ans);
    }
	return 0;
}

解法二:莫比烏斯反演。

其中"設F(a,b,k)表示有多少組x≤a,y≤b,且Gcd(a,b)≥k"的"Gcd(a,b)>=k"應該是k | Gcd(x,y)。

java怎么解決歐拉函數和莫比烏斯反演問題

/*********************************************************
  file name: hdu1695.cpp
  author : kereo
  create time:  2015年02月12日 星期四 09時08分41秒
*********************************************************/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<cmath>
#include<string>
#include<algorithm>
using namespace std;
typedef long long ll;
const int sigma_size=26;
const int N=100+50;
const int MAXN=100000+50;
const int inf=0x3fffffff;
const double eps=1e-8;
const int mod=1000000000+7;
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define PII pair<int, int>
#define mk(x,y) make_pair((x),(y))
int primecnt;
int vis[MAXN],mu[MAXN],prime[MAXN],sum[MAXN];
void Mobius(){
    primecnt=0;
    memset(vis,0,sizeof(vis));
    mu[1]=1;
    for(int i=2;i<MAXN;i++){
        if(!vis[i]){
            prime[primecnt++]=i;
            mu[i]=-1;
        }
        for(int j=0;j<primecnt && i*prime[j]<MAXN;j++){
            vis[i*prime[j]]=1;
            if(i%prime[j]) 
                mu[i*prime[j]]=-mu[i];
            else{
                mu[i*prime[j]]=0;
                break;
            }
        }
    }
}
ll solve(int l,int r){
    ll ans=0;
    if(l>r)
        swap(l,r);
    int last;
    for(int i=1;i<=l;i=last+1){
        last=min(l/(l/i),r/(r/i));
        ans+=(ll)(sum[last]-sum[i-1])*(ll)(l/i)*(ll)(r/i);
    }
    return ans;
}
int main(){
    int T,kase=0;
    Mobius();
    sum[0]=0;
    for(int i=1;i<MAXN;i++)
        sum[i]=sum[i-1]+mu[i];
    scanf("%d",&T);
    while(T--){
        int a,b,c,d,k;
        printf("Case %d: ",++kase);
        scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
        if(k == 0 || k>b || k>d){
            printf("0\n");
            continue;
        }
        if(b>d)
            swap(b,d);
        b/=k; d/=k;
        printf("%I64d\n",solve(b,d)-solve(b,b)/2);
    }
	return 0;
}

讀到這里,這篇“java怎么解決歐拉函數和莫比烏斯反演問題”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。

向AI問一下細節
推薦閱讀:
  1. 歐拉函數
  2. DFS序,歐拉序

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

西乌珠穆沁旗| 双江| 延吉市| 蕲春县| 社旗县| 霍城县| 肃北| 马龙县| 湄潭县| 资讯| 泽州县| 昌黎县| 车险| 云浮市| 富裕县| 陆丰市| 黑山县| 会同县| 彭州市| 琼中| 平乐县| 乌什县| 青浦区| 台州市| 宁化县| 靖宇县| 五台县| 阿拉善左旗| 嫩江县| 建昌县| 蓝田县| 永川市| 莱阳市| 崇礼县| 龙山县| 崇明县| 绥阳县| 桦川县| 犍为县| 南宫市| 徐汇区|