zoukankan      html  css  js  c++  java
  • [bzoj3930] [CQOI2015]选数

    Description

    我们知道,从区间[L,H](L和H为整数)中选取N个整数,总共有(H-L+1)^N种方案。小z很好奇这样选出的数的最大公约数的规律,他决定对每种方案选出的N个整数都求一次最大公约数,以便进一步研究。然而他很快发现工作量太大了,于是向你寻求帮助。你的任务很简单,小z会告诉你一个整数K,你需要回答他最大公约数刚好为K的选取方案有多少个。由于方案数较大,你只需要输出其除以1000000007的余数即可。

    Input

    输入一行,包含4个空格分开的正整数,依次为N,K,L和H。

    Output

    输出一个整数,为所求方案数。

    Sample Input

    2 2 2 4
    

    Sample Output

    3
    

    HINT

    样例解释

    所有可能的选择方案:(2, 2), (2, 3), (2, 4), (3, 2), (3, 3), (3, 4), (4, 2), (4, 3), (4, 4)

    其中最大公约数等于2的只有3组:(2, 2), (2, 4), (4, 2)

    对于100%的数据,1≤N,K≤10 ^ 9,1≤L≤H≤10^9 ,H-L≤10^5

    solution

    这题似乎有神仙容斥/dp啥的解法?

    考虑大力莫比乌斯反演,考虑(L)(R)内gcd为(k)的方案本质上和(L/k)(R/k)内gcd为1的相同,

    可得:

    [egin{align} ans&=sum_{a_1=L}^Rsum_{a_2=L}^Rdotssum_{a_n=L}^R[gcd(a_1,a_2,dots,a_n)=k]\ &=sum_{d=1}^{lfloorfrac{R}{d} floor}mu(d)(lfloorfrac{R}{kd} floor-lfloorfrac{L-1}{kd} floor)^n end{align} ]

    然后对于(sum mu(d)),可以大力杜教筛,然后就做完了。

    关于莫比乌斯反演,安利一波:莫比乌斯反演

    #include<bits/stdc++.h>
    using namespace std;
    
    #define int long long 
    
    void read(int &x) {
    	x=0;int f=1;char ch=getchar();
    	for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    	for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
    
    void print(int x) {
    	if(x<0) x=-x,putchar('-');
    	if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    const int maxn = 1e7+1;
    const int mod = 1000000007;
    
    int pri[maxn],mu[maxn],vis[maxn],tot;
    
    void sieve() {
    	mu[1]=1;
    	for(int i=2;i<maxn;i++) {
    		if(!vis[i]) pri[++tot]=i,mu[i]=-1;
    		for(int t,j=1;j<=tot&&i*pri[j]<maxn;j++) {
    			vis[t=i*pri[j]]=1;
    			if(!(i%pri[j])) {mu[t]=0;break;}
    			mu[t]=-mu[i];
    		}
    	}
    	for(int i=1;i<maxn;i++) mu[i]=mu[i-1]+mu[i];
    }
    
    map<int,int > Mu;
    
    int sum_mu(int n) {
    	if(n<maxn) return mu[n];
    	if(Mu[n]) return Mu[n];//write(n);
    	int ans=1,T=2;
    	while(T<=n) {
    		int pre=T;T=n/(n/T);
    		ans=(ans-(T-pre+1)*sum_mu(n/T)%mod)%mod;T++;
    	}
    	return Mu[n]=(ans%mod+mod)%mod;
    }
    
    int qpow(int a,int x) {
    	int res=1;
    	for(;x;x>>=1,a=a*a%mod) if(x&1) res=res*a%mod;
    	return res;
    }
    
    signed main() {
    	sieve();
    	int l,r,k,n;read(n),read(k),read(l),read(r);
    	int T=1,ans=0;r/=k,l--,l/=k;
    	while(T<=r) {
    		int pre=T;T=min(r/(r/T),l/T?l/(l/T):-1u>>1);
    		ans=(ans+(sum_mu(T)-sum_mu(pre-1))%mod*qpow((r/T)-(l/T),n)%mod)%mod;T++;
    	}
    	write((ans%mod+mod)%mod);
    	return 0;
    }
    
    
  • 相关阅读:
    算法竞赛入门经典习题2-3 韩信点兵
    ios入门之c语言篇——基本函数——5——素数判断
    ios入门之c语言篇——基本函数——4——数值交换函数
    144. Binary Tree Preorder Traversal
    143. Reorder List
    142. Linked List Cycle II
    139. Word Break
    138. Copy List with Random Pointer
    137. Single Number II
    135. Candy
  • 原文地址:https://www.cnblogs.com/hbyer/p/10076978.html
Copyright © 2011-2022 走看看