1. 程式人生 > >東林oj 1541 數字三角形加強版

東林oj 1541 數字三角形加強版

題目連結 https://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1541
本題用到:楊輝三角,利用逆元求組合數,快速冪。
剛開始,想到的是矩陣連乘,按照題目要求寫了6行圖形,發現其實是楊輝三角加快速冪。
三角形中的數設為xAx1Bx2 ,那麼x在三角形中就是楊輝三角。F[i][j]=A∗F[i−1][j]+B∗F[i−1][j−1] 式子中除去A和B,與楊輝三角中每個數等於它上方兩數之和是相似。
並且第n行每個數A和B的指數和為n-1,第一個為An-1B0,然後A的指數減一,B的指數加一,直到A0Bn-1(找規律得到的,不會推)。
綜上所述,第n行第m個數的值為C(n-1,m-1)An-m

Bm-1.
先打表求出範圍內的階乘,再求階乘的逆元,0的階乘的逆元學長的模板裡沒有(學長應該用了特判),當時樣例輸出為0,感覺慌得一批,幸虧我機智,想到0的階乘為1,逆元也為1(太機智了)
然後輸入a b n m,利用c(n-1,m-1)=(n-1)!/((n-m)!*(m-1)!)。求出c(n-1,m-1),再利用快速冪求出)An-mBm-1。相乘取模結束。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 100009
#define mod 1000000009
using namespace std;
long long fac[N],inv[N];
long long quickmod(long long n,long long m)
{
    long long b=1;
    while(m>0)
    {
        if(m&1)
            b=b*n%mod;
        n=n*n%mod;
        m=m>>1;
    }
    return b;
}
void  ints()
{
      fac[0]=1;
    for(int i=1;i<=N;i++)
    {
         fac[i]=fac[i-1]*i%mod;///求組合式
        // printf("%lld\n",fac[i]);
    }
    inv[0]=1;///學長的模板裡沒有  要注意
    inv[N]=quickmod(fac[N],mod-2);
    for(int i=N-1;i>=1;i--)
        inv[i]=inv[i+1]*(i+1)%mod;///求組合數的逆元
}
int main()
{
      long long t,x,x1,x2,a,b,n,m,sum;
      int i;
      memset(fac,0,sizeof(fac));
      memset(inv,0,sizeof(inv));
      ints();
      //for(i=1;i<25;i++)
       //printf("%lld\n",inv[i]);
      scanf("%lld",&t);
      while(t--)
      {
          scanf("%lld%lld%lld%lld",&a,&b,&n,&m);
          x=(fac[n-1]*inv[m-1])%mod;
          //printf("%lld\n",x);
          x=x*inv[n-m]%mod;
           //printf("%lld\n",x);
          x1=quickmod(a,n-m);
          x2=quickmod(b,m-1);
          sum=x*x1%mod;
          sum=sum*x2%mod;
          printf("%lld\n",sum);
      }
    return 0;