GLV HDU6482 HDU5852

GLV的maxn开两倍,防止溢出。

HDU6482

题意:给你x1,x2,y1,y2  (x1<x2,y1<y2),问你从(0,y1)->(x1,0),(0,y2)->(0,x2),只能往右、往下走的时候的路径不相交的条数是多少。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int mod=(int)1e9+7;
 5 const int maxn=200005;
 6 ll fac[maxn+5],inv_fac[maxn+5];
 7 
 8 ll quick(ll a,ll b){
 9     ll ans=1;
10     while(b){
11         if(b&1) ans=ans*a%mod;
12         a=a*a%mod;
13         b/=2;
14     }
15     return ans;
16 }
17 void init(){
18     inv_fac[0]=fac[0]=1,fac[1]=inv_fac[1]=1;
19     for(int i=2;i<maxn;i++)
20         fac[i]=fac[i-1]*i%mod;
21     inv_fac[maxn-1]=quick(fac[maxn-1],mod-2);
22     for(int i=maxn-2;i>=0;i--)
23         inv_fac[i]=inv_fac[i+1]*(i+1)%mod;
24 }
25 
26 ll C(ll n,ll m){
27     if(n<0||m<0||m>n) return 0;
28     if(n==m||m==0) return 1;
29     return fac[n]*inv_fac[n-m]%mod*inv_fac[m]%mod;
30 }
31 ll x[2],y[2];
32 int main(){
33     init();
34     int t;
35     cin>>t;
36     while(t--){
37         scanf("%lld%lld%lld%lld",&x[0],&x[1],&y[0],&y[1]);
38         ll ans1=C(x[1]+y[1],y[1]),ans2=C(x[0]+y[1],y[1]);
39         ll ans3=C(y[0]+x[1],y[0]),ans4=C(x[0]+y[0],y[0]);
40         printf("%lld\n",((ans1*ans4-ans2*ans3)%mod+mod)%mod);
41 
42     }
43    return 0;
44 }

HDU5852

题意:给你一个n*n的矩阵,再第一行一次有k个起点1<=a1<a2<a3<...<ak<=n;最后一行有n个终点1<=b1<b2<b3<...<bk<=n;你只能向右或向下走,问你有多少种路线方案,使得ai->bi  i=1...n;答案mod 1e9+7

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <vector>
  5 using namespace std;
  6 typedef long long int ll;
  7 
  8 const int MAXN = 2e5 + 10;
  9 ll jc[MAXN];
 10 ll inv[MAXN];
 11 
 12 
 13 
 14 const ll MOD = 1e9 + 7;
 15 const int N = 1e2 + 10;
 16 ll a[N][N];
 17 
 18 ll pow(ll a, ll n, ll p)    //快速幂 a^n % p
 19 {
 20     ll ans = 1;
 21     while (n) {
 22         if (n & 1) ans = ans * a % p;
 23         a = a * a % p;
 24         n >>= 1;
 25     }
 26     return ans;
 27 }
 28 
 29 ll niYuan(ll a, ll b)   //费马小定理求逆元
 30 {
 31     return pow(a, b - 2, MOD);
 32 }
 33 
 34 
 35 inline ll C(int a, int b)    //计算C(a, b),a下,b上
 36 {
 37     if (b > a) return 0;
 38     return jc[a] * inv[b] % MOD
 39         * inv[a - b] % MOD;
 40 }
 41 
 42 void init()
 43 {
 44     ll p = 1;
 45     jc[0] = 1;
 46     jc[1] = 1;
 47     inv[0] = 1;
 48     inv[1] = 1;
 49     for (int i = 2;i < MAXN;i++) {
 50         p = (p * i) % MOD;
 51         jc[i] = p;
 52         //inv[i]=inv[MOD%i]*(MOD-MOD/i)%MOD;
 53     }
 54 
 55     for (int i = 2;i < MAXN;i++) inv[i] = inv[MOD % i] * (MOD - MOD / i) % MOD;   //O(n)求逆元
 56     for (int i = 2;i < MAXN;i++) inv[i] = inv[i - 1] * inv[i] % MOD;   //扩展到i!的逆元
 57 }
 58 
 59 
 60 ll determinant(int n)
 61 {
 62     //a为方阵
 63     //MOD根据实际情况而定
 64     ll ans = 1;
 65     for (int k = 1;k <= n;k++)  //将a[k+1..n][k]都变成0
 66     {
 67         ll pos = -1;
 68         for (int i = k;i <= n;i++)  //找到a[k..n][k]中第一个非0元素
 69             if (a[i][k])
 70             {
 71                 pos = i;
 72                 break;
 73             }
 74         if (pos == -1)return 0;  //没有的话行列式值为0
 75         if (pos != k)  //将找到的那一行换到第k行,swap(a[k],a[pos])
 76             for (int j = k;j <= n;j++)swap(a[pos][j], a[k][j]);
 77         ll inv = niYuan(a[k][k], MOD);
 78         for (int i = k + 1;i <= n;i++)
 79             if (a[i][k])
 80             {
 81                 ans = ans * inv % MOD;   //下面的计算中第i行提高a[k][k]倍,所以答案需要除以a[k][k]才是正解
 82                 for (int j = k + 1;j <= n;j++)
 83                     a[i][j] = ((a[i][j] * a[k][k] % MOD - a[k][j] * a[i][k] % MOD) % MOD + MOD) % MOD;
 84                 a[i][k] = 0;
 85             }
 86     }
 87     for (int i = 1;i <= n;i++)
 88         ans = ans * a[i][i] % MOD;
 89     return ans;
 90 }
 91 
 92 int A[N], B[N];
 93 
 94 
 95 int main()
 96 {
 97     int t;
 98     init();
 99     scanf("%d", &t);
100     while (t--)
101     {
102         int n, k;
103         scanf("%d%d", &n, &k);
104         for (int i = 1;i <= k;i++) scanf("%d", &A[i]);
105         for (int i = 1;i <= k;i++) scanf("%d", &B[i]);
106 
107         for (int i = 1;i <= k;i++)
108         {
109             for (int j = 1;j <= k;j++)
110             {
111                 a[i][j] = C(n + B[j] - (1 + A[i]), n - 1);
112             }
113         }
114         printf("%lld\n", determinant(k));
115     }
116 }

 

posted @ 2020-03-21 10:28  programmer_w  阅读(1)  评论(0)    收藏  举报