fireworks
Problem 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?
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.
Sample Input
1 2 0 2 2 2 2 2 0 3 1 2
Sample Output
2 3
Hint
Source
“浪潮杯”山东省第八届ACM大学生程序设计竞赛(感谢青岛科技大学)
题意:
烟花在每秒都会分裂一次,并且分裂成的两半刚好落在相邻的两点,然后它们也可以继续分裂。
给出 n
个点烟花的初始数量,问经过 T
秒后在点 w
有多少数量的烟花。
题解:
考虑所有的烟花分裂都是一样的,并且其分裂之后所形成的局势仅和时间有关。
所以我们只需要关心一个烟花是如何分裂的:
0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 1 0 1 0 0 0 0
0 0 0 1 0 2 0 1 0 0 0
0 0 1 0 3 0 3 0 1 0 0
0 1 0 4 0 6 0 4 0 1 0
第几行代表第几秒,行中的每个数字代表当前时间该点烟花的数量,于是我们发现了一个中间插入了 0
的杨辉三角,计算方法也就是组合数咯~
从上面的矩阵我们可以发现,当时间与距离同奇偶的时候才处于杨辉三角中,其余情况都为 0
。
因为题目中数据比较大,所以计算组合数需要用到乘法逆元,先打表求出 n!
,然后根据组合数公式计算即可。
(思路来自千千)
代码:
#include<bits/stdc++.h>
using namespace std;
/// IO Input and Output
namespace IO
{
template <typename T>
inline bool scan_d (T &ret)
{
char c;
int sgn;
if (c = getchar(), c == EOF)return false; //EOF
while (c != '-' && (c < '0' || c > '9') )
if((c = getchar()) == EOF) return false;
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return true;
}
template<typename T>
void print(T x)
{
static char s[33], *s1;
s1 = s;
if (!x) *s1++ = '0';
if (x < 0) putchar('-'), x = -x;
while(x) *s1++ = (x % 10 + '0'), x /= 10;
while(s1-- != s) putchar(*s1);
}
template<typename T>
void println(T x)
{
print(x);
putchar('\n');
}
};
typedef long long ll;
const int maxn = 2e5+10;
const ll mod = 1e9+7;
ll arr[maxn],tot;
ll fac[maxn],inv[maxn];
ll power(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() {
fac[0] = fac[1] = 1;
inv[0] = inv[1] = 1;
for(int i=2;i<maxn;i++) {
fac[i] = fac[i-1] * i % mod;
inv[i] = power(fac[i],mod-2);
}
}
ll C(ll n,ll m) {
return fac[n] * (inv[m] * inv[n-m] % mod) % mod;
}
void init_t(int t) {
memset(arr,0,sizeof(arr));
tot = 0;
int len = t / 2;
if(t % 2 == 0) arr[tot++] = C(t,len--);
for(int i = len;i >= 0;i--)
arr[tot++] = 0,arr[tot++] = C(t,i);
}
int main()
{
init();
int n,t,w;
while(~IO::scan_d(n),IO::scan_d(t),IO::scan_d(w))
{
init_t(t);
ll ans = 0;
int x,c;
for(int i=0;i<n;i++) {
scanf("%d%d",&x,&c);
ans = ( ans + (ll)arr[abs(x-w)] * c % mod ) % mod;
}
IO::println(ans);
}
return 0;
}