HDU 6333 Harvest of Apples (分塊、數論)


題目連接:Harvest of Apples

題意:給出一個n和m,求C(0,n)+C(1,n)+.....+C(m,n)。(樣例組數為1e5)

題解:首先先把階乘和逆元預處理出來,這樣就可O(1)將C(m,n)求出來了。但這樣還是會超時,所以接下來要分塊,每隔500個處理出C(1~m,n)的結果。然后還要知道一個性質 C(a,b) = ∑C(t1,x)*C(t2,y)  (x+y<=b),這樣我們就可以將給出的m和n分為兩個組,其中一個組中元素的個數為500的倍數。然后我們對於另一個組枚舉可能的t2然后求和,每次詢問最大的操作次數就變成了500次。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const LL mod = 1e9 + 7;
 5 typedef pair<int,int> P;
 6 const int MAX_N = 1e5+9;
 7 int N,M,T,S;
 8 LL Jc[MAX_N];
 9 LL ni_[MAX_N];
10 LL tran[309][MAX_N];
11 LL tr[509][509];
12 //費馬小定理求逆元
13 LL pow(LL a, LL n, LL p)    //快速冪 a^n % p
14 {
15     LL ans = 1;
16     while(n)
17     {
18         if(n & 1) ans = ans * a % p;
19         a = a * a % p;
20         n >>= 1;
21     }
22     return ans;
23 }
24 
25 LL niYuan(LL a, LL b)   //費馬小定理求逆元
26 {
27     return pow(a, b - 2, b);
28 }
29 
30 void calJc()    //求maxn以內的數的階乘
31 {
32     Jc[0] = Jc[1] = 1;
33     for(LL i = 2; i < MAX_N; i++)
34         Jc[i] = Jc[i - 1] * i % mod;
35 }
36 void calni(){
37     for(int i=0;i<MAX_N;i++){
38         ni_[i] = niYuan(Jc[i],mod);
39     }
40 }
41 
42 LL C(LL a, LL b)    //計算C(a, b)
43 {
44     return Jc[a] * ni_[b] % mod
45         * ni_[a-b] % mod;
46 }
47 
48 void init(){
49     for(int i=1;i<MAX_N/500;i++){
50         for(int j=0;j<MAX_N;j++){
51             tran[i][j] = C(500*i,j);
52             if(j>0) tran[i][j] = (tran[i][j] + tran[i][j-1])%mod;
53         }
54     }
55 
56     for(int i=0;i<509;i++){
57         for(int j=0;j<509;j++){
58             tr[i][j] = C(i,j);
59         }
60     }
61 }
62 int main(){
63     calJc();
64     calni();
65     init();
66     //cout<<"OK"<<endl;
67     cin>>T;
68     while(T--){
69         LL a,b;
70         scanf("%lld%lld",&a,&b);
71         LL ans = 0;
72         if(a < 500){
73             for(int i=0;i<=b;i++)
74                 ans = (ans + tr[a][i])%mod;
75         }
76         else{
77             LL t1 = a / 500;
78             LL t2 = a - t1*500;
79             for(int i=0;i<=min(b,t2);i++){
80                 ans = (ans + tr[t2][i]*tran[t1][min(b - i,t1*500)])%mod;
81             }
82         }
83         printf("%lld\n",ans);
84 
85     }
86     return 0;
87 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM