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[20]; const int inf=0x3f3f3f3f; const ll infll = 0x3f3f3f3f3f3f3f3fLL; inline ll read() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } inline void P(int x) { Num=0;if(!x){putchar('0');puts("");return;} while(x>0)CH[++Num]=x%10,x/=10; while(Num)putchar(CH[Num--]+48); puts(""); } //************************************************************************************** int pow_mod(int x, int k) { int ans=1; while(k) { if(k & 1) ans = 1LL * ans * x % mod; x = 1LL * x * x % mod; k >>= 1; } 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-1;i>=1;i--) { int L=l/i,R=r/i; if(l%i)L++; if(l<=r) { ans[i]=pow_mod(R-L+1,n); ans[i]=(ans[i]-(R-L+1)+mod)%mod; for(int j=i*2;j<maxn;j+=i) ans[i]=(ans[i]-ans[j]+mod)%mod; } } if(l==1) ans[1]=(ans[1]+1)%mod; P(ans[1]); }