Problem B. Harvest of Apples(杭电2018年多校+组合数+逆元+莫队)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6333

题目:

题意:求C(n,0)+C(n,1)+……+C(n,m)的值。

思路:由于t和n数值范围太大,所以此题查询复杂度不能太高,由组合数的将前k项求和可以推出,从而可以转换成莫队的区间查询,将n当成l,m当成r即可。此题需要注意,对于求组合数得用o(1)的方法求,也就是阶乘相除的方法,对于分母我们得求逆元,因而借助欧拉定理。

代码实现如下:

 1 #include <set>
 2 #include <map>
 3 #include <queue>
 4 #include <stack>
 5 #include <cmath>
 6 #include <bitset>
 7 #include <cstdio>
 8 #include <string>
 9 #include <vector>
10 #include <cstdlib>
11 #include <cstring>
12 #include <iostream>
13 #include <algorithm>
14 using namespace std;
15 
16 typedef long long ll;
17 typedef pair<ll, ll> pll;
18 typedef pair<ll, int> pli;
19 typedef pair<int, ll> pil;;
20 typedef pair<int, int> pii;
21 typedef unsigned long long ull;
22 
23 #define lson i<<1
24 #define rson i<<1|1
25 #define bug printf("*********\n");
26 #define FIN freopen("D://code//in.txt", "r", stdin);
27 #define debug(x) cout<<"["<<x<<"]" <<endl;
28 #define IO ios::sync_with_stdio(false),cin.tie(0);
29 
30 const double eps = 1e-8;
31 const int mod = 1e9 + 7;
32 const int maxn = 1e5 + 7;
33 const double pi = acos(-1);
34 const int inf = 0x3f3f3f3f;
35 const ll INF = 0x3f3f3f3f3f3f3f;
36 
37 int t, block;
38 ll sum;
39 ll a[maxn], b[maxn];
40 
41 struct node {
42     int l, r, id;
43     ll ans;
44     bool operator < (const node & x) const {
45         return (l - 1) / block == (x.l - 1) / block ? r < x.r : l < x.l;
46     }
47 }ask[maxn];
48 
49 ll Mod_Pow(ll x, ll n) {
50     ll res = 1;
51     while(n > 0) {
52         if(n & 1) res = res * x % mod;
53         x = x * x % mod;
54         n >>= 1;
55     }
56     return res;
57 }
58 
59 void init() {
60     a[1] = 1;
61     for(int i = 2; i < maxn; i++) a[i] = a[i-1] * i % mod;
62     for(int i = 1; i < maxn; i++) b[i] = Mod_Pow(a[i], mod - 2);
63 }
64 
65 ll C(int n, int m) {
66     if(n < 0 || m < 0 || m > n) return 0;
67     if(m == 0 || m == n) return 1;
68     return a[n] * b[n-m] % mod * b[m] % mod;
69 }
70 
71 int main() {
72     //FIN;
73     init();
74     scanf("%d", &t);
75     block = sqrt(maxn);
76     sum = 1;
77     for(int i = 1; i <= t; i++) {
78         scanf("%d%d", &ask[i].l, &ask[i].r);
79         ask[i].id = i;
80     }
81     sort(ask + 1, ask + t + 1);
82     for(int i = 1, l = 1, r = 0; i <= t; i++) {
83         while(l < ask[i].l) sum = (2 * sum - C(l++, r) + mod) % mod;
84         while(l > ask[i].l) sum = ((sum + C(--l, r)) * b[2]) % mod;
85         while(r < ask[i].r) sum = (sum + C(l, ++r)) % mod;
86         while(r > ask[i].r) sum = (sum - C(l, r--) + mod) % mod;
87         ask[ask[i].id].ans = sum;
88     }
89     for(int i = 1; i <= t; i++) {
90         printf("%lld\n", ask[i].ans);
91     }
92     return 0;
93 }

 

转载于:https://www.cnblogs.com/Dillonh/p/9404788.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值