zoukankan      html  css  js  c++  java
  • 【BZOJ3930】选数

    【BZOJ3930】选数

    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)
    【数据范围】
      对于30%的数据,N≤5,H-L≤5
      对于100%的数据,1≤N,K≤10^9,1≤L≤H≤10^9,H-L≤10^5

    我们先将(r=lfloor frac{r}{k} floor,l=lfloor frac{l-1}{k} floor)
    然后我们直接用套路了:(displaystylesum_{d=1}^{l}mu(d)(lfloor frac{r}{k} floor-lfloor frac{l}{k} floor)^{n})

    然后处理(mu(d))的前缀和的时候要用杜教筛。

    代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define N 10000005
    
    using namespace std;
    inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}
    
    const ll mod=1000000007;
    ll n,k,l,r;
    bool vis[N];
    int pri[N],mu[N];
    void pre(int n) {
    	mu[1]=1;
    	for(int i=2;i<=n;i++) {
    		if(!vis[i]) {
    			pri[++pri[0]]=i;
    			mu[i]=-1;
    		}
    		for(int j=1;j<=pri[0]&&1ll*i*pri[j]<=n;j++) {
    			vis[i*pri[j]]=1;
    			if(i%pri[j]==0) {
    				mu[i*pri[j]]=0;
    				break;
    			}
    			mu[i*pri[j]]=-mu[i];
    		}
    	}
    	for(int i=1;i<=n;i++) mu[i]+=mu[i-1]; 
    }
    
    map<int,int>sum;
    ll cal(ll n) {
    	if(n<=1e7) return mu[n];
    	if(sum.find(n)!=sum.end()) return sum[n];
    	ll ans=1,last;
    	for(int i=2;i<=n;i=last+1) {
    		last=n/(n/i);
    		ans-=(last-i+1)*cal(n/i);
    	}
    	return sum[n]=ans;
    }
    
    ll ksm(ll t,ll x) {
    	ll ans=1;
    	for(;x;x>>=1,t=t*t%mod)
    		if(x&1) ans=ans*t%mod;
    	return ans;
    }
    
    ll solve(ll l,ll r) {
    	ll ans=0,last;
    	for(ll i=1;i<=r;i=last+1) {
    		ll x=!(l/i)?r:l/(l/i),y=r/(r/i);
    		last=min(x,y);
    		ans=(ans+(cal(last)-cal(i-1)+mod)*ksm(r/i-l/i,n)%mod)%mod;
    	}
    	return ans;
    }
    
    int main() {
    	pre(10000000);
    	n=Get(),k=Get(),l=Get(),r=Get();
    	l=(l-1)/k;
    	r/=k;
    	cout<<solve(l,r);
    	return 0;
    }
    
  • 相关阅读:
    【插件开发】—— 10 JFace开发详解
    百度地图POI数据爬取,突破百度地图API爬取数目“400条“的限制11。
    Python3中遇到UnicodeEncodeError: 'ascii' codec can't encode characters in ordinal not in range(128)
    Python 3.X 要使用urllib.request 来抓取网络资源。转
    python创建目录保存文件
    Python返回数组(List)长度的方法
    python中for、while循环、if嵌套的使用
    (转)python3 urllib.request.urlopen() 错误UnicodeEncodeError: 'ascii' codec can't encode characters
    python 之 string() 模块
    (转)Python3异常-AttributeError: module 'sys' has no attribute 'setdefaultencoding
  • 原文地址:https://www.cnblogs.com/hchhch233/p/9996558.html
Copyright © 2011-2022 走看看