3930: [CQOI2015]选数

Time Limit: 20 Sec

Memory Limit: 256 MB

题目连接

http://www.lydsy.com/JudgeOnline/problem.php?id=3930

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

题意

题解:

记f[i]为gcd恰好为K*i的选数方案数
那么对于每一个i 记L为 a/(K*i) 上取整 R为 b/(K*i) 那么他的方案数就为
(R-L+1) ^ N - (R-L+1) 再减去f[a*i] (a = 1,2,3....)
最后的f[1]即为答案 注意若a/K上取整 == 1 那么全部选K也是一种方案 需要+1

转自:http://blog.csdn.net/shiyukun1998/article/details/44922391

讲的很清楚

代码:

//qscqesze
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
//freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define test freopen("test.txt","r",stdin)
#define maxn 100001
#define mod 1000000007
#define eps 1e-9
int Num;
char CH[];
const int inf=0x3f3f3f3f;
const ll infll = 0x3f3f3f3f3f3f3f3fLL;
inline ll read()
{
ll x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
inline void P(int x)
{
Num=;if(!x){putchar('');puts("");return;}
while(x>)CH[++Num]=x%,x/=;
while(Num)putchar(CH[Num--]+);
puts("");
}
//**************************************************************************************
int pow_mod(int x, int k)
{
int ans=;
while(k) {
if(k & ) ans = 1LL * ans * x % mod;
x = 1LL * x * x % mod;
k >>= ;
}
return ans;
}
int ans[maxn];
int main()
{
//test;
int n,k,a,b;
n=read(),k=read(),a=read(),b=read();
int l=a/k,r=b/k;
if(a%k)l++;
for(int i=maxn-;i>=;i--)
{
int L=l/i,R=r/i;
if(l%i)L++;
if(l<=r)
{
ans[i]=pow_mod(R-L+,n);
ans[i]=(ans[i]-(R-L+)+mod)%mod;
for(int j=i*;j<maxn;j+=i)
ans[i]=(ans[i]-ans[j]+mod)%mod;
}
}
if(l==)
ans[]=(ans[]+)%mod;
P(ans[]);
}
05-02 08:56