9.27模拟

T1【JSOI2011】分特产

题目分析

很容易想到求补集,即有人没有特产的方案数。

我们枚举有至少多少个人没有土特产。

那么补集的答案就是至少1个人没有土特产的方案数-至少2个人没有土特产的方案数+至少3个人没有土特产的方案数-...。

那么至少\(i\)个人没有土特产的方案数怎么求呢?

对于每一种土特产,我们要分给剩余\(n-i\)个人,方案数即为\(C^{n-i-1}_ {m+n-i-1}\)

因此预处理出组合数,枚举\(i\)统计即可。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int mod=1000000007;
int n,m,a[2005],c[2005][2005];
void init(){
	c[0][0]=1;
	for(int i=1;i<=2000;i++){
		c[i][0]=1;
		for(int j=1;j<=i;j++)c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
	}
}
int main(){
	init();
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)scanf("%d",&a[i]);
	int ans=0;
	for(int i=0;i<=n;i++){
		int sum=1,tot=n-i,f=(i&1)?1:-1;
		for(int j=1;j<=m;j++)sum=1ll*sum*c[a[j]+tot-1][tot-1]%mod;
		ans=(ans+1ll*-f*c[n][i]%mod*sum)%mod;
	}
	cout<<(ans+mod)%mod<<"\n";
}

T2 【PA2014】Final Zarowki

题目分析

挖坑代填

T3 【JLOI2015】城池攻占

题目分析

一眼倍增啊。观察数据范围,发现乘的都是正数。那么显然无论怎么乘、加减,最终战斗力都能写成\(a* x+b(a>0)\)这样的式子。那么对于这个一次函数显然\(x\)是单调递增的。因此我们可以对于树上每一个点\(i\)倍增求出从\(i\)向上占领\(2^j\)步,所需的最小战斗力\(lim[i][j]\)。同时预处理出\(Mul[i][j],Plus[i][j]\)表示从\(i\)向上占领\(2^j\)步后战斗力\(x\)应变为\(Mul[i][j]* x+Plus[i][j]\)

#include <bits/stdc++.h>
using namespace std;
inline char Getchar(){
	static char buffer[1<<20],*S,*T=S;
	return T==S?T=(S=buffer)+fread(buffer,1,1<<20,stdin),*S++:*S++;
}
template<class T>
inline void read(T &x){
	x=0;T f=1;char ch=getchar();
	while(!isdigit(ch))ch!='-'?:f=-1,ch=getchar();
	while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
	x*=f;
}
typedef long long ll;
const int Maxn=300005;
int n,m,h[Maxn],p[Maxn][20],dep[Maxn],cnt[Maxn],ans[Maxn];
ll Mul[Maxn][20],Plus[Maxn][20];
long double lim[Maxn][20];
struct node{
	ll a,v,h;
}a[Maxn];
int main(){
//	freopen("attack.in","r",stdin);
//	freopen("attack.out","w",stdout);
	read(n);read(m);
	for(int i=1;i<=n;i++)read(a[i].h);
	for(int i=0;i<=18;i++)Mul[0][i]=Mul[1][i]=1;
	for(int i=1;i<=n;i++){
		if(i!=1)read(p[i][0]),read(a[i].a),read(a[i].v);
		dep[i]=dep[p[i][0]]+1;
		if(a[i].a)Plus[i][0]=0,Mul[i][0]=a[i].v;
		else Plus[i][0]=a[i].v,Mul[i][0]=1;
		lim[i][0]=a[i].h;
		for(int j=1;j<=18;j++){
			p[i][j]=p[p[i][j-1]][j-1];
			Plus[i][j]=Plus[i][j-1]*Mul[p[i][j-1]][j-1]+Plus[p[i][j-1]][j-1];
			Mul[i][j]=Mul[i][j-1]*Mul[p[i][j-1]][j-1];
			lim[i][j]=max(lim[i][j-1],(lim[p[i][j-1]][j-1]-Plus[i][j-1])/Mul[i][j-1]);
		}
	}
	for(int i=1;i<=m;i++){
		ll s;int c;
		read(s);read(c);
		int t=c;
		for(int j=18;~j;j--)if(lim[t][j]<=s){
			s=s*Mul[t][j]+Plus[t][j];t=p[t][j];
		}
		cnt[t]++;ans[i]=dep[c]-dep[t];
	}
	for(int i=1;i<=n;i++)cout<<cnt[i]<<"\n";
	for(int i=1;i<=m;i++)cout<<ans[i]<<"\n";
}
/*
x*a+b>=lim
x*a>=lim-b
x>=(lim-b)/a
*/
posted @ 2018-09-27 13:26  Trrui  阅读(94)  评论(0编辑  收藏  举报