【提前声明:此题没有通过!WA!有待进一步研究修改。放在这里只是起一个例子的作用,其实这道题鄙人并没有真正掌握= =】、
【本文努力抄袭模仿了小花妹妹的博文0戳我0)】
题目大意:共T个测试点,每个测试点中,给定n、m,求将不超过m个种子放入n个坑的方案总数,最后答案对质数p取模。(一共m个,每个坑放多少无所谓,最后没放完m个也无所谓)
数据范围:1 <= n, m <= 1000000000, 1 < p < 100000。
思路:原题意即求方程x1+…+xn=m解的个数,因为中间的每一项均可为0,故两面同时将加上n,转换成为x1+…+xn+n=m+n,即x1’+…+xn’=m+n,其中每一项至少为1,则由隔板法可知,解的个数为C(n+m-1,m),这只是恰好为m个的方案数,总数为ans=C(n-1,0)+C(n,1)+…+C(n+m-1,m)=C(n+m,m)。(注意,这里组合数的意思表示为:n+m选m个)
知识储备:
注意:中途必须强制转换类型,否则出错。【但没有人知道为什么而且最后还是挂了】
//HDU3037 Saving Beans Lucas¶¨Àí×éºÏÊýÈ¡Ä£ //copyright by ametake #include<iostream> using namespace std; typedef long long ll; ll t,n,m,p; ll multi(ll a,ll b) { ll ans=1; while (b>0) { if (b & 1 == 1) ans=((ll)ans*(ll)a)%p; a =( (ll)a * (ll)a ) % p; b =(ll)(b << 1); } return ans; } ll c(ll n,ll m) { ll a=1,b=1; if (m>n) return 0; while (m) { a=(a*n)%p; b=(b*m)%p; m--; n--; } return ((ll)a*(ll)multi(b,p-2))%p; } ll lucas(ll n,ll m,ll p) { if ( !m ) return 1; else return ( (ll)lucas(n/p,m/p,p)*(ll)c(n%p,m%p)&p); } int main() { cin>>t; for (ll i=1;i<=t;i++) { cin>>n>>m>>p; cout<<lucas(n+m,m,p)<<endl; } return 0; }
下一站就要转战DP海洋了···挣扎的小鱼啊···
但无论如何古诗词是不能少的
——凄凉别后两应同,最是不胜清怨月明中。
【日常学习】【组合数取模Lucas定理】HDU3037 Saving Beans题解
原文地址:http://blog.csdn.net/ametake/article/details/46550659