The 2018 ACM-ICPC China JiangSu Provincial Programming Contest快速幂取模及求逆元

题目来源

The 2018 ACM-ICPC China JiangSu Provincial Programming Contest

35.4%

  • 1000ms
  • 65536K

Persona5 is a famous video game.

In the game, you are going to build relationship with your friends.

You have N friends and each friends have his upper bound of relationship with you. Let's consider the ithi^{th}ith friend has the upper bound UiU_iUi. At the beginning, the relationship with others are zero. In the game, each day you can select one person and increase the relationship with him by one. Notice that you can't select the person whose relationship with you has already reach its upper bound. If your relationship with others all reach the upper bound, the game ends.

It's obvious that the game will end at a fixed day regardless your everyday choices. Please calculate how many kinds of ways to end the game. Two ways are said to be different if and only if there exists one day you select the different friend in the two ways.

As the answer may be very large, you should output the answer mod 1000000007

Input Format

The input file contains several test cases, each of them as described below.

  • The first line of the input contains one integers N(1≤N≤1000000)(1 le N le 1000000)(1N1000000), giving the number of friends you have.
  • The second line contains NNN integers. The ithi^{th}ith integer represents UiU_iUi(1≤Ui≤1000000)( 1 le U_i le 1000000)(1Ui1000000), which means the upper bound with ithi^{th}ith friend. It's guarantee that the sum of UiU_iUi is no more than 1000000.

There are no more than 10 test cases.

Output Format

One line per case, an integer indicates the answer mod 1000000007.

样例输入

3
1 1 1
3
1 2 3

样例输出

6
60
题目大意:有n个朋友,开始和每个朋友的关系为0,给出每个朋友的关系上限,每天只能和一个朋友的关系度增加1,求有多少种方式能够和他们的关系都达到上限。
解题思路:这道题很明显就是高中数学里面的排列组合题,我们可以先忽略先后顺序,直接把每个关系度看成一个朋友然后去掉是同一朋友的关系度,本质就是多重集合的排列计数问题 令 sum=a(1)+a(2)+。。。+a(n) ,答案就是 sum!/a1!a2!...an! 需要先打表,预处理逆元跟阶乘,否则会超时 复杂度:O(nlogn)(预处理)
附上AC代码:
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=1e6+1;
 5 const int mod=1e9+7;
 6 ll fac[maxn],facinv[maxn];
 7 ll n,a[maxn];
 8 
 9 ll qpow(ll a,ll b,ll p)  //快速幂取模
10 {
11     ll res=1;
12     while(b)
13     {
14         if(b&1) res=res*a%p;
15         b>>=1;
16         a=a*a%p;
17     }
18     return res;
19 }
20 
21 void init()  //求出阶乘与逆元
22 {
23     fac[0]=fac[1]=facinv[0]=facinv[1]=1;
24     for(int i=2;i<maxn;i++)
25     {
26         fac[i]=fac[i-1]*i%mod;
27         facinv[i]=facinv[i-1]*qpow(i,mod-2,mod)%mod;
28     }
29 }
30 
31 int main()
32 {
33     init();
34     while(cin>>n)
35     {
36         ll sum=0;
37         ll ans=1;
38         for(int i=1;i<=n;i++)
39         {
40             scanf("%d",&a[i]);
41             sum+=a[i];
42             ans=ans*facinv[a[i]]%mod;
43         }
44         ans=ans*fac[sum]%mod;
45         printf("%d
",ans);
46     }
47     return 0;
48 }

 求逆元参考博客:https://blog.csdn.net/baidu_35643793/article/details/75268911

原文地址:https://www.cnblogs.com/zjl192628928/p/9383166.html