端午节个人赛-山东省省赛 fireworks(杨辉三角形+组合数+逆元)

来源:互联网 发布:工程动画软件 编辑:程序博客网 时间:2024/05/29 18:29

Description

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?

img 
 

Input

Input contains multiple test cases.

For each test case:

The first line contains 3 integers n,T,w(n,T,|w|≤10^5)

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|≤10^5).

 

Output

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

 

Example Input

1 2 02 22 2 20 31 2

 

Example Output

23

 

题意

烟花在每秒都会分裂一次,并且分裂成的两半刚好落在相邻的两点,然后它们也可以继续分裂。

给出 n 个点烟花的初始数量,问经过 T 秒后在点 w 有多少数量的烟花。

 

思路

考虑所有的烟花分裂都是一样的,并且其分裂之后所形成的局势仅和时间有关。

所以我们只需要关心一个烟花是如何分裂的:

0 0 0 0 0 1 0 0 0 0 00 0 0 0 1 0 1 0 0 0 00 0 0 1 0 2 0 1 0 0 00 0 1 0 3 0 3 0 1 0 00 1 0 4 0 6 0 4 0 1 0

第几行代表第几秒,行中的每个数字代表当前时间该点烟花的数量,于是我们发现了一个中间插入了 0 的杨辉三角,计算方法也就是组合数咯~

从上面的矩阵我们可以发现,当时间与距离同奇偶的时候才处于杨辉三角中,其余情况都为 0 。


因为题目中数据比较大,所以计算组合数需要用到乘法逆元,先打表求出 n! ,然后根据组合数公式计算即可。

  注意点:

1、理解逆元的概念,知道杨辉三角形与组合数的对应关系;

对于正整数,如果有,那么把这个同余方程中的最小正整数解叫做的逆元。

逆元一般用扩展欧几里得算法来求得,如果为素数,那么还可以根据费马小定理得到逆元为

     

2、大数据,%mod多多益善

3、思路清晰,分块写,稳一点

4、读懂题意!!

#include <iostream>#include <cstdio>#include <cstring>#include <math.h>#include <stdlib.h>using namespace std;typedef long long ll;const ll mod = 1e9 + 7;ll j[101000], ex[101000];ll ppow(ll a, ll b)                        //求快速幂{    //cout << a << " " << b <<endl;    a %= mod; b %= mod;    ll ans = 1;    while(b)    {        if(b&1) ans = (ans % mod * a) % mod;        a = a * a % mod;        b /= 2;    }   // cout << "PP" << ans << endl;    return ans % mod;                           }void init()                                  //初始化n!的值和 n!取模1e9+7时的逆元{    j[0] = ex[0] = 1;    for(int i = 1; i <= 100005; i ++ )    {        j[i] = i * j[i-1] % mod;        ex[i] = ppow(j[i], mod - 2) % mod;    }    return ;}int C(int n, int m)                    //求组合数 C(N, M);{    if(n == m) return 1;    ll ans = j[n] % mod * ex[n-m] % mod * ex[m] % mod;    //cout << j[n] << " " << ex[n-m] <<" " << ex[m] << endl;    //cout << "CC" << ans << endl;    return ans;}int main(){  //  freopen("1.txt", "r", stdin);    int n, t, w;    init();    //cout << ex[1] << endl;    while(cin >> n >> t >> w)    {        int c, x;        ll ans = 0;        for(int i = 1; i <= n; i++)        {            int c, x;            cin >> x >> c;            int k = abs(w - x) % mod;            if(k > t || (k&1) != (t&1) || !c) continue;         //注意如果 k和t奇偶性不同或者k > t的话ans是不会变化的            ans += c % mod * C(t, (k + t) / 2) % mod;      //我也不知道为什么 c 后面加了个 %mod 就不会wa了2333....            ans %= mod;        }        cout << ans % mod << endl;    }    return 0;}


阅读全文
0 0
原创粉丝点击