E. Placing Jinas
题目大意:每个点相当于(0,0)到每个点(只能向下和向右走)的方法数量
每行的白方块从左到右一共有a[ i ]个,问白方格里的总和是多少
1 1 1 1 1 1 1 2 3 4 5 6 1 3 6 10 15 21 1 4 10 20 35 56 1 5 15 35 70 126 1 6 21 56 126 252
可以发现这是类似组合数的表,C(i,j)是每个格子的大小,很容易想到全遍历一遍,但是这样显然太慢
所以观察发现每一行最后一个(i,a[i])的累加和为C(i+1,a[i]),O(N)就可以算完
用到快速幂求逆元和组合数
代码
#include<bits/stdc++.h>
#define debug0(x) cout << "debug0: " << x << endl
#define fr(t, i, n) for (int i = t; i < n; i++)
#define first fi
#define second se
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
LL qmi(LL a,int b,int p)//快速幂在于思想
{
LL res=1;
while(b)//对b进行二进制化,从低位到高位
{
if(b&1) res = res *a %p;
b>>=1;
a=a*a%p;
}
return res % p;
}
const int N = 5e5+10,mod = 1e9+7;
LL fact[N];//,inv[N];
void solve(){
int n;cin >> n;
fact[0] /*= inv[0]*/ = 1;
for(int i = 1;i < N;i ++)fact[i] = fact[i-1]*i%mod;
//inv[N-1]=qmi(fact[N-1],mod-2,mod); for(int i=N-2;i>=1;i--) inv[i]=inv[i+1]*(i+1)%mod;
//for(int i = 0;i < N;i ++)assert(inv[i] == qmi(fact[i],mod-2,mod));
LL ans = 0;
fr(0,i,n+1){
int a;cin >> a;
if(a < 1)continue;
ans = (ans + (fact[a+i]*qmi(fact[i+1],mod-2,mod)%mod)*qmi(fact[a-1]%mod,mod-2,mod)%mod)%mod;
//ans = (ans + (fact[a+i]*inv[i+1]%mod)*inv[a-1]%mod)%mod;
}
cout << ans << endl;
}
int main()
{
/*
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
*/
int T = 1;
while(T--){
solve();
}
return 0;
}