haut oj 1299 fireworks(杨辉三角规律)

题目链接

1299: fireworks
时间限制: 1 秒 内存限制: 64 MB
提交: 42 解决: 16
提交 状态
题目描述

Hmz likes to play fireworks, especially when they are put regularly.
Now he puts some fireworks in a line. This time he put a trigger on each firework. With that trigger, each firework will explode and split into two parts per second, which means if a firework is currently in position x, then in next second one part will be in position x−1 and one in x+1. They can continue spliting without limits, as Hmz likes.

Now there are n fireworks on the number axis. Hmz wants to know after T seconds, how many fireworks are there in position w?

输入

Input contains multiple test cases.
For each test case:

The first line contains 3 integers n,T,w(n,T,|w|≤105)
In next n lines, each line contains two integers xi and ci, indicating there are ci fireworks in position xi at the beginning(ci,|xi|≤105).
输出

For each test case, you should output the answer MOD 1000000007.

样例输入

1 2 0
2 2
2 2 2
0 3
1 2
样例输出

2
3
提示

题意,有n个火苗,每个火苗每秒会分成两个,在左右相邻的位置各一个,自己这个位置的火苗消失,问你在T秒过后,在W这个位置会有多少个火苗

思路: 把火苗的分裂图如果画下来,就会发现他是一个杨辉三角,不过对于中间有些位置的0可以进行特判。
这里写图片描述

第一行为0秒时,第二行为1秒时,所以第T秒后,应该在(T+1)行,然后得到w与x的距离就知道它是第几个元素,最左边的从0开始,可直凡是在奇数位的都为0,偶数位置除以2,就能转化为杨辉三角的图形了。注意组合树的取模,这里是先求阶乘把它存到数组里

完整代码如下:

#include<iostream>
#include<cstring>
#include<set>
#include<vector>
#include<algorithm>
#include<map>

using namespace std;
typedef long long ll;
const int MAX = 100010;
const ll MOD = 1000000007;
ll N,T,W;
ll Quick_pow(ll x,ll n){
    ll res = 1;
    while(n){
        if(n & 1)   res = res*x % MOD;
        x = x*x % MOD;
        n >>= 1;
    }
    return res;
}
ll f[MAX];
void init(){//预处理阶乘
    f[0] = 1;
    for(int i=1;i<=100000;++i){
        f[i] = f[i-1]*i % MOD;
    }
}
ll Get(ll n,ll m){//组合数
    ll res;
    res = f[n]*Quick_pow(f[m],MOD-2)%MOD * Quick_pow(f[n-m],MOD-2) % MOD;
    return res;
}

int main(void){
    init();
    while(scanf("%lld%lld%lld",&N,&T,&W) != EOF){
        ll res = 0,x,y;
        for(int i=1;i<=N;i++){
            scanf("%lld %lld",&x,&y);
            ll dis = abs(W-x);
            if(dis > T) continue;
            ll m = T - dis;
            if(m % 2 == 1)  continue;
            m /= 2;
            res = (res + y*Get(T,m)) % MOD;
        }
        printf("%lld\n",res);
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值