数论(CRB and Candies,HDU 5407)
2017-07-22 21:26
232 查看
题目链接:https://vjudge.net/problem/HDU-5407
暴力打了个表,感觉找不到什么规律。
1
2
3
12
10
60
105
280
252
2520
2310
27720
25740
24024
45045
720720
想把整个表全部打完估计要一整天。
然后规律是g[i]=lcm(1,2,...,i,i+1)/(i+1)。
然后有公式lcm(1,2,...,n)=(n==p^k)?lcm(1,2,...,n-1)*p:lcm(1,2,...,n-1)
我感觉还是挺难找到规律的吧。。
具体数论上的公式就是
b
=lcm(1,2,...,n)=(n==p^k)?b[n-1]*p:b[n-1]
a
=lcm(C(n,0),C(n,1),...,C(n,n))=b[n+1]/(n+1)
p是某个质数。
参考博客:
http://www.cnblogs.com/liyinggang/p/5578654.html
http://www.cnblogs.com/aoxuets/p/4746278.html
也看到有人通过思考找到了简单的规律
http://www.cnblogs.com/crazyacking/p/4748294.html
具体思路就是考虑求lcm(C(n,0),C(n,1),...,C(n,n))
可以考虑对每一项唯一分解,然后维护每个质数的最高次数,最后乘起来就是答案。
数与数之间的联系还是挺强的。
毕竟有公式C(n,k)=C(n,k-1)*(n-k+1)/k
而且组合数是对称的,所以其实只用求一半。
暴力做肯定是要超时的,毕竟一次回答需要O(n^2)
可以考虑从这个规律入手,找到一些简便的算法。
对于当前项C(n,k),我们比之前新引入了一个因子(n-k+1),同时也删除了一个因子k。
好吧,其实我不太明白。
最后还有数列网
http://oeis.org/
一查就知道了。
跟别人的差距很大
两份代码
暴力打了个表,感觉找不到什么规律。
1
2
3
12
10
60
105
280
252
2520
2310
27720
25740
24024
45045
720720
想把整个表全部打完估计要一整天。
然后规律是g[i]=lcm(1,2,...,i,i+1)/(i+1)。
然后有公式lcm(1,2,...,n)=(n==p^k)?lcm(1,2,...,n-1)*p:lcm(1,2,...,n-1)
我感觉还是挺难找到规律的吧。。
具体数论上的公式就是
b
=lcm(1,2,...,n)=(n==p^k)?b[n-1]*p:b[n-1]
a
=lcm(C(n,0),C(n,1),...,C(n,n))=b[n+1]/(n+1)
p是某个质数。
参考博客:
http://www.cnblogs.com/liyinggang/p/5578654.html
http://www.cnblogs.com/aoxuets/p/4746278.html
也看到有人通过思考找到了简单的规律
http://www.cnblogs.com/crazyacking/p/4748294.html
具体思路就是考虑求lcm(C(n,0),C(n,1),...,C(n,n))
可以考虑对每一项唯一分解,然后维护每个质数的最高次数,最后乘起来就是答案。
数与数之间的联系还是挺强的。
毕竟有公式C(n,k)=C(n,k-1)*(n-k+1)/k
而且组合数是对称的,所以其实只用求一半。
暴力做肯定是要超时的,毕竟一次回答需要O(n^2)
可以考虑从这个规律入手,找到一些简便的算法。
对于当前项C(n,k),我们比之前新引入了一个因子(n-k+1),同时也删除了一个因子k。
好吧,其实我不太明白。
最后还有数列网
http://oeis.org/
一查就知道了。
跟别人的差距很大
两份代码
#include<stdio.h> #include<vector> #include<math.h> using namespace std; typedef long long ll; const int maxn = 1000010; const int mod = 1e9+7; vector<int>pri; int vis[maxn]; void getpri() { int m = sqrt(maxn+0.5); for(int i=2;i<=m;i++) if(!vis[i]) for(int j=i*i;j<maxn;j+=i) vis[j]=1; for(int i=2;i<maxn;i++) if(!vis[i]) pri.push_back(i); } void solve() { int n; scanf("%d",&n); int ans=1; for(int i=0;i<(int)pri.size();i++) for(ll j=pri[i];j<=n;j*=pri[i]) if((n+1)%j!=0) ans=1ll*ans*pri[i]%mod; printf("%d\n",ans); } int main() { getpri(); int T; scanf("%d",&T); while(T--) solve(); return 0; }
#include<stdio.h> #include<vector> #include<math.h> using namespace std; typedef long long ll; const int maxn = 1000010; const int mod = 1e9+7; vector<int>pri; int vis[maxn]; int mul[maxn]; int f[maxn]; int g[maxn]; int inv[maxn]; int mp(int x,int n) { int ret=1; while(n) { if(n&1) ret=1ll*ret*x%mod; x=1ll*x*x%mod; n>>=1; } return ret; } void getpri() { for(int i=0;i<maxn;i++) inv[i]=mp(i,mod-2); int m = sqrt(maxn+0.5); for(int i=2;i<=m;i++) if(!vis[i]) for(int j=i*i;j<maxn;j+=i) vis[j]=1; for(int i=2;i<maxn;i++) if(!vis[i]) pri.push_back(i); for(int i=0;i<maxn;i++) mul[i]=1; for(int i=0;i<(int)pri.size();i++) for(ll j=pri[i];j<maxn;j*=pri[i]) mul[j]=pri[i]; f[1]=1; for(int i=2;i<maxn;i++) { f[i]=1ll*f[i-1]*mul[i]%mod; g[i-1]=1ll*f[i]*inv[i]%mod; } } void solve() { int n; scanf("%d",&n); printf("%d\n",g ); } int main() { getpri(); int T; scanf("%d",&T); while(T--) solve(); return 0; }
相关文章推荐
- HDU 5407 CRB and Candies(数论+yy)
- HDU 5407 CRB and Candies 数论
- hdu 5407 CRB and Candies(数论)
- hdu 5407 CRB and Candies(数论,LCM,快速幂取模,求逆元)
- 【数论】 HDOJ 5407 CRB and Candies
- 数论 HDOJ 5407 CRB and Candies
- HDU 5407(2015多校10)-CRB and Candies(组合数最小公倍数+乘法逆元)
- HDU 5407 CRB and Candies
- hdu 5407 CRB and Candies 2015多校联合训练赛#10 找规律 素数筛法
- hdu 5407 CRB and Candies
- HDU 5407 CRB and Candies(LCM +最大素因子求逆元)
- HDU 5407 CRB and Candies (2015年多校比赛第10场)
- hdu 5407 CRB and Candies(素数筛选法,除法取模(乘法逆元))
- LCM性质 + 组合数 - HDU 5407 CRB and Candies
- hdu 5407 CRB and Candies(乘法逆元+快速幂)
- hdu 5407 CRB and Candies(组合数+最小公倍数+素数表+逆元)2015 Multi-University Training Contest 10
- HDU 5407(2015多校10)-CRB and Candies(组合数最小公倍数+乘法逆元)
- HDU 5407 CRB and Candies (2015多校第10场第一题)素数打表,除法取模(乘法逆元)
- HDU 5407 CRB and Candies(数学 素数表+预处理+快速幂+乘法逆元)——多校练习10
- HDU 5407(CRB and Candies-OEIS)