NKOJ3823 水果怪
时间限制 : - MS 空间限制 : 165536 KB
评测说明 : 1000ms
问题描述
小南和小开在三友路上养了很多只果冻怪。我们可以将三友路想象成一根长度无限的数 轴,在这上面生活着n只果冻怪。每经过一秒,一只果冻怪便会分裂成两只。具体来说,一 只坐标为x的果冻怪,会分裂成两只分别在(x − 1),(x + 1)上的果冻怪,并且原来在x上的果 冻怪会消失。 由于生存空间有限,若一个位置上有不少于P只果冻怪,那么会立刻消失 P 只。经过测 定P = 10^9 + 7。 小南和小开想知道在第T秒末,位置w有多少只果冻怪。初始时刻是0秒初。
输入格式
第一行为三个整数,n,T,w。含义如题所述。
接下来 n 行,每行两个整数xi,ci,表示xi位置,有ci只果冻怪。注意xi可能有重复。
输出格式
输出一个非负整数,表示 T 秒末 w 位置上的果冻怪个数
样例输入
2 2 2
0 3
1 2
样例输出
3
提示
对于 30%的数据: 1 ≤ n ≤ 100,1 ≤ T ≤ 16。
对于 60%的数据:1 ≤ n ≤ 10^5,1 ≤ T ≤ 16。
对于 100%的数据:1 ≤ n,T,ci ≤ 10^5,0 ≤ |w|,|xi| ≤ 10^5。
来源 WJJ
思路:
只有一只水果怪时,T秒产生的水果怪分布正好为T的所有组合数
因为只考虑正好T秒,采用组合数线性递推 c[n][i]=c[n][i-1] * (n-i+1)/i
注意:
组合数下标与水果怪下标需转换
因为有除法,所以需要使用逆元
#include<cstdio>
#include<iostream>
using namespace std;
const int need=1e5+90;
const long long mod=1e9+7;
int c[need*2];
//--------------------------------------------------------------------------------
inline void in_(int &d)
{
char t=getchar();bool mark=false;
while(t<'0'||t>'9') {if(t=='-') mark= true;t=getchar();}
for(d=0;!(t<'0'||t>'9');t=getchar()) d=(d<<1)+(d<<3)+t-'0';
if(mark) d=-d;
}
//--------------------------------------------------------------------------------
int ni(int a,int b=mod-2,int c=mod)
{
a%=c;
int ans=1;
while(b)
{
if(b&1) ans=(long long)ans*a%c;
b>>=1;
a=(long long)a*a%c;
}
return ans;
}
//--------------------------------------------------------------------------------
int main()
{
int n,w,t;scanf("%d%d%d",&n,&t,&w);
//int *c=s+(100000<<1);
c[0]=1;
for(int i=2,tt=t<<1;i<=tt;i+=2) c[i]=((long long)c[i-2]*(t-i/2+1)%mod)*ni(i/2)%mod;///(i/2);
//c+=t;
int ans=0;
for(int i=1,a,b,r=n*2-1;i<=n;i++)
{
in_(a),in_(b);
if(t+w-a<=r&&t+w-a>=0)ans=((long long)ans+(long long)c[t+w-a]*b%mod)%mod;
}
cout<<ans;
}