3930: [CQOI2015]选数|递推|数论
2016-03-23 20:07
260 查看
题目让求从区间[L,H]中可重复的选出n个数使其gcd=k的方案数
转化一下也就是从区间[⌈Lk⌉,⌊Hk⌋]中可重复的选出n个数使其gcd=1的方案数
然后f[i]表示gcd=i的方案数,考虑去掉所有的数都是重复的情况,这种情况最后在判断一下加上
f[i]=sum−∑i|jf[j]
转化一下也就是从区间[⌈Lk⌉,⌊Hk⌋]中可重复的选出n个数使其gcd=1的方案数
然后f[i]表示gcd=i的方案数,考虑去掉所有的数都是重复的情况,这种情况最后在判断一下加上
f[i]=sum−∑i|jf[j]
#include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<vector> #include<cmath> #include<queue> #include<set> #include<map> #define ll long long #define mod 1000000007 //2 3 4679 35617 #define N 100051 using namespace std; int sc() { int i=0,f=1; char c=getchar(); while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar(); return i*f; } long long f ,n,k,a,b; long long cal(ll x,ll y) { long long res=1; for(;y;x=x*x%mod,y>>=1) if(y&1)res=res*x%mod; return res; } int main() { scanf("%d%d%d%d",&n,&k,&a,&b); int l=a/k,r=b/k; if(a%k)l++; for(int i=b-a;i;i--) { int L=l/i,R=r/i; if(l%i)L++; if(l<=r) { f[i]=(cal(R-L+1,n)-(R-L+1))%mod; for(int j=i*2;j<=b-a;j+=i)f[i]=(f[i]-f[j])%mod; } } if(l==1)f[1]++; printf("%d",(f[1]+mod)%mod); return 0; }
相关文章推荐
- C语言竞赛——数字序列
- 【HDU 5366】The mook jong 详解
- ACM常用算法
- HDU 2569
- N个结点能组成多少种二叉树
- SICP Exercise 1.13
- Jump Game
- SGU 181 X-Sequence(傻逼题)
- 对于一个数字,我们可以直观的了解到它所含有的数字,例如: 3243中包含1个2、2个3、1个4。 那么,给你一个数n,求从1到n之间的所有这些数字中,总共包含多少个m。
- [BZOJ1179][APIO2009][Tarjan][拓扑排序][递推]Atm
- [BZOJ1089][SCOI2003][递推][高精度]严格n元树
- [DP]FJSDFZOJ 1143 数字三角形
- [DP]NOIP2002/FJSDFZOJ 1081 过河卒
- hdu1003 Max Sum
- DP 递推j计数
- hdoj 2501 Tiling_easy version(递推)
- hdu1465 不容易系列之一(错排)
- 2050——折线分割平面
- 2049——不容易系列之(4)——考新郎
- 2048——神、上帝以及老天爷