zoukankan      html  css  js  c++  java
  • luogu P3172 [CQOI2015]选数 |容斥原理

    题目描述

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

    由于方案数较大,你只需要输出其除以 (10^9+7) 的余数即可。

    输入格式

    输入一行,包含四个空格分开的正整数,依次为 (N,K,L,H)

    输出格式

    输出一个整数,为所求方案数除以 (10^9 + 7) 的余数。


    (f[i])表示选出的数的最大公约数(i)且选出的数不全相同的方案数


    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define int long long
    const int N=1e5+5,mod=1e9+7;
    inline int read(){
        int x=0,f=1; char ch=getchar();
        while(ch>'9'||ch<'0'){ if(ch=='-')f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9'){ x=x*10+ch-'0'; ch=getchar(); }
        return x*f;
    }
    int f[N];
    inline int ksm(int a, int b) {
        int res=1;
        while(b){
            if(b&1)res=res*a%mod;
            a=a*a%mod; b>>=1;
        }
        return res;
    }
    signed main(){
    	int n=read(),k=read(),l=read(),h=read();
    	if(l%k)l=l/k+1; else l/=k;	h/=k;
    	if(l>h){ puts("0"); return 0; }
    	for(int i=1;i<=h-l;i++){
    		int L=l,R=h;
    		if(L%i)L=L/i+1; else L/=i; R/=i;
    		if(L>R)continue;
    		f[i]=(ksm(R-L+1,n)-(R-L+1)+mod)%mod;
    	}
    	for(int i=h-l;i;i--) for(int j=(i<<1);j<=h-l;j+=i)f[i]=(f[i]-f[j]+mod)%mod;
    	if(l==1)f[1]=(f[1]+1)%mod;
    	cout<<f[1]<<endl;
    	return 0;
    }
    
  • 相关阅读:
    linux读写锁
    正则表达式
    C++原型模式和模板模式
    C++外观模式和组合模式
    C++代理模式
    c++桥接模式
    Linux常用命令history/tcpdump/awk/grep
    C++委托模式
    c++ 读写锁
    布衣客
  • 原文地址:https://www.cnblogs.com/naruto-mzx/p/13095591.html
Copyright © 2011-2022 走看看