• bzoj 3930: [CQOI2015]选数


    Description

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

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

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

    解题报告:老套路设(f_i)表示gcd为i的方案数,转化为求[L/K,R/K]中互质的数对个数,答案即为(f_1),考虑这一题数据范围较大,且(H-L<=10^5),那么就需要用到结论:假设N个数不全相同,那么他们的最大公约数小于最大和最小的两个数之差,正确性显然,所以我们把状态改为:(f_i)表示选n个互不相同的数,gcd为i的方案数
    令L=L/K,R=R/K
    那么[L,R]间含i这个因子的数有(R/i)-((L-1)/i)种,所以选n个的方案数一共有((R/i-(L-1)/i)^n),再减去所有数都重复的((R/i-(L-1)/i))种,减完之后的值设为(tot),然后就是推(fi),因为现在的方案只是包含i这个因子,而不是gcd=i的方案,所以还要减去gcd不为i的方案
    综上:(f_i=tot-sum_{j=i*2}^{j=R-L}f_j)

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #define RG register
    #define il inline
    #define iter iterator
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    using namespace std;
    typedef long long ll;
    const int N=1e5+5,mod=1000000007;
    ll qm(ll x,ll k){
    	ll sum=1;
    	while(k){
    		if(k&1)sum*=x,sum%=mod;
    		x*=x;x%=mod;k>>=1;
    	}
    	return sum;
    }
    ll f[N];
    void work()
    {
    	int n,L,R,K;
    	cin>>n>>K>>L>>R;
    	bool flg=(L<=K && K<=R);
    	L--;L/=K;R/=K;int c=R-L;
    	ll l,r;
    	for(int i=c;i>=1;i--){
    		l=L/i;r=R/i;
    		f[i]=((qm(r-l,n)-(r-l)%mod)+mod)%mod;
    		for(int j=2;j*i<=c;j++)
    			f[i]-=f[j*i],f[i]=(f[i]%mod+mod)%mod;
    	}
    	f[1]+=flg;f[1]%=mod;
    	printf("%lld
    ",f[1]);
    }
    
    int main()
    {
    	work();
    	return 0;
    }
    
    
  • 相关阅读:
    将博客搬至CSDN
    Redis快速入门详解
    Linux下离线安装MySQL
    Git-如何将已存在的项目提交到git
    linux下修改完profile文件的环境变量后如何立即生效
    Redis允许远程连接
    Spring Boot中使用Swagger2构建强大的RESTful API文档
    JVM内存结构
    java类的加载机制
    linux 内存查看
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7466706.html
Copyright © 2020-2023  润新知