東林oj 1541 數字三角形加強版
阿新 • • 發佈:2018-11-04
題目連結 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
先打表求出範圍內的階乘,再求階乘的逆元,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;