2018 Multi-University Training Contest 4--Problem B. Harvest of Apples--hdu--6333

Problem B. Harvest of Apples

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 3018    Accepted Submission(s): 1180

 

Problem Description

There are n apples on a tree, numbered from 1 to n.
Count the number of ways to pick at most m apples.

Input

The first line of the input contains an integer T (1≤T≤105) denoting the number of test cases.
Each test case consists of one line with two integers n,m (1≤m≤n≤105).

Output

For each test case, print an integer representing the number of ways modulo 109+7.

Sample Input

2

5 2

1000 500

Sample Output

16

924129523

Source

2018 Multi-University Training Contest 4

题意:

给你n,m两个数,问你在n个中最多取m个有多少种取法。

使用算法:

莫队 + 组合数 + 逆元

题解:

其实就是求C_{n}^{0} +C_{n}^{1}+C_{n}^{2}...+C_{n}^{m}S_{n}^{m}

这个题组合数求模时,需要用到逆元,逆元可以避免除法,将除变为乘,即当\frac{a}{b} \ mod \ p = \frac{a}{b} *1\ mod \ p=\frac{a}{b}*c\ mod \ p = a*c\ mod \ p时,此时c称为a的逆元。

假设c是b的逆元 b*c = 1\ \( mod \ p) ①,根据费马小定理:gcd(a, p) = 1 时,a^{p-1} \ mod \ p = 1 ② (p表示素数)

联立①②可得:b*c = c^{p-1}\mod p\Rightarrow b = c^{p-2}  所以模(p-2)就好

然后回到这题,显而易见可以得到{\color{Red} S_{n}^{m}=S_{n}^{m-1}+C_{n}^{m}}

根据组合数的递推公式

C_{n}^{m} = C_{n-1}^{m} + C_{n-1}^{m-1}

S_{n}^{m} = C_{n}^{0} +C_{n}^{1}+C_{n}^{2}...+C_{n}^{m}

S_{n}^{m} = C_{n-1}^{0} +(C_{n-1}^{1} +C_{n-1}^{0})+(C_{n-1}^{2} + C_{n-1}^{1})...+(C_{n-1}^{m}+C_{n-1}^{m-1})

S_{n}^{m}=2 * (C_{n-1}^{0} +C_{n-1}^{1}+C_{n-1}^{2}...+C_{n-1}^{m-1})+C _{n}^{m}

{\color{Red} S_{n}^{m}=2 * S_{n-1}^{m}-C _{n-1}^{m}}

把上式的S_{n}^{m}变成S_{n}^{m-1}或者S_{n}^{m+1} 得到:

{\color{Red} S_{n-1}^{m}=(S_{n}^{m}+C _{n-1}^{m}) / 2}

{\color{Red} S_{n+1}^{m}=2*S_{n}^{m}-C _{n}^{m}}

根据红字的公式用莫队离线操作

#include<bits/stdc++.h>
using namespace std;

#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define MP make_pair
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=b;i>=a;i--)
#define ll long long
#define int64 __int64

const ll mod = 1e9 + 7;
const ll MAXN = 1e5 + 5;
const ll MAXM = 1e9 + 5;

struct node {
	int n,m,id;
} A[MAXN];

int pos[MAXN];
ll inv[MAXN],num[MAXN],ans[MAXN];

int cmp(node x,node y) {
	if(pos[x.n] != pos[y.n]) {
		return x.n < y.n;
	}
	return x.m < y.m;
}

ll quickpow(ll a,ll b) {
	ll ans=1;
	while(b) {
		if(b&1) {
			ans=(ans*a)%mod;
		}
		a=(a*a)%mod;
		b>>=1;
	}
	return ans;
}

void init() {
	num[1] = 1;
	for(int i = 2; i < MAXN; i++) num[i] = (num[i-1] *i)%mod;
	for(int i = 1; i < MAXN; i++) inv[i] = quickpow(num[i],mod -2);
}
ll C(int n, int m) {
	if(n < 0 || m < 0 || m > n) return 0;
	if(m == 0|| m == n) return 1;
	return num[n] * inv[n - m]%mod*inv[m]%mod;
}
ll res = 1;

int main() {
	init();
	int t;
	scanf("%d",&t);
	int block = sqrt(MAXN);
	rep(i,1,MAXN - 1) pos[i] = (i - 1) / block;
	rep(i,1,t) {
		scanf("%d%d",&A[i].n,&A[i].m);
		A[i].id = i;
	}
	sort(A+1,A+t+1,cmp);
	int N = 1,M = 0;
	rep(i,1,t) {
		while(N<A[i].n)res = (2*res - C(N++,M)+mod)%mod;
		while(N>A[i].n) res=((res+C(--N,M))*inv[2])%mod;
		while(M<A[i].m) res=(res+C(N,++M))%mod;
		while(M>A[i].m) res=(res-C(N,M--)+mod)%mod;
		ans[A[i].id]=res;
	}
	rep(i,1,t)
	printf("%lld\n", ans[i]);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
大学生就业服务平台管理系统按照操作主体分为管理员和用户。管理员的功能包括学生档案管理、字典管理、试卷管理、试卷选题管理、试题表管理、考试记录表管理、答题详情表管理、错题表管理、法律法规管理、法律法规收藏管理、法律法规留言管理、就业分析管理、论坛管理、企业管理、简历管理、老师管理、简历投递管理、新闻资讯管理、新闻资讯收藏管理、新闻资讯留言管理、学生信息管理、宣传管理、学生管理、职位招聘管理、职位收藏管理、招聘咨询管理、管理员管理。用户的功能等。该系统采用了Mysql数据库,Java语言,Spring Boot框架等技术进行编程实现。 大学生就业服务平台管理系统可以提高大学生就业服务平台信息管理问题的解决效率,优化大学生就业服务平台信息处理流程,保证大学生就业服务平台信息数据的安全,它是一个非常可靠,非常安全的应用程序。 管理员权限操作的功能包括管理新闻信息,管理大学生就业服务平台信息,包括考试管理,培训管理,投递管理,薪资管理等,可以管理新闻信息。 考试管理界面,管理员在考试管理界面中可以对界面中显示,可以对考试信息的考试状态进行查看,可以添加新的考试信息等。投递管理界面,管理员在投递管理界面中查看投递种类信息,投递描述信息,新增投递信息等。新闻信息管理界面,管理员在新闻信息管理界面中新增新闻信息,可以删除新闻信息。新闻信息类型管理界面,管理员在新闻信息类型管理界面查看新闻信息的工作状态,可以对新闻信息的数据进行导出,可以添加新新闻信息的信息,可以编辑新闻信息信息,删除新闻信息信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值