RQNOJ85 三个袋子 题解、、

来源:互联网 发布:元老院 知乎 笑话 编辑:程序博客网 时间:2024/04/28 21:50

题目:三个袋子
问题编号:85
题目描述
背景
平平在公园里游玩时捡到了很多小球,而且每个球都不一样。平平找遍了全身只发现了3个一模一样的袋子。他打算把这些小球都装进袋子里(袋子可以为空)。他想知道他总共有多少种放法。
题目描述
将N个不同的球放到3个相同的袋子里,求放球的方案总数M。
结果可能很大,我们仅要求输出M mod K的结果。
现在,平平已经统计出了N<=10的所有情况。见下表:
N 1 2 3 4 5 6 7 8 9 10
M 1 2 5 14 41 122 365 1094 3281 9842
数据规模
对于 40%数据,10<=N<=10,000
对于100%数据,10<=N<=1,000,000,000
对于 100%数据,K<=100,000

输入格式
两个整数N,K,N表示球的个数。

输出格式
输出仅包括一行,一个整数M mod K 。

样例输入
11 10000

样例输出
9525
这道题目考察的内容为组合数学。如果每个袋子不一样,球也不一样,那么总方案数为3^n;

但是现在袋子是一样的。于是需要除以3的全排列即3! 但是在袋子一样的情况下,如果所有的球都装在一个袋子中,另外两个袋子是一样的。于是方案就漏算了。由于有三个袋子,所以方案数要加上3再除以3的全排列。于是方案总数变成了 (3^n+3)/3!

化简一下变成(3^(n-1)+1)/2;输出的答案变成了 (3^(n-1)+1)/2 mod k; 如果直接计算,这个结果会很大。导致数字超出范围。于是需要用到快速幂;但是这个算式中又出现了出发,如果要在快速幂中加入出发,那么程序会很难写,而且还需要用带很多高级的定理,于是我从另一个方向出发。将算式化为 ((3^(n-1)+1) mod (2*k) )div 2,这个式子看起来似乎很复杂,但是用于编程就会变的灰常好用了。这个化简需要用到一个定理:(a div b) mod c =(a mod bc)/b;

然后式子就可是这样表达:((3^(n-1)mod 2*k +1)mod 2*k ) div 2;其中3^(n-1) mod 2*k 是经典的快速幂算法;

最后贴一下核心代码:

Begin       Readln(n,k);       a:=3;b:=n-1;c:=2*k;       while(b>0)do       begin              if(bmod 2=1)then ans:=ans*a mod c;              b:=bdiv 2;              a:=(a*a)mod c;end;ans:=(ans+1)modc;ans:=ans div 2;writeln(ans);End;

Ps:注意一下,所有的变量都改用int64,不然会Wa 掉一个点。

0 0
原创粉丝点击