贴一个题目链接:http://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Index/problemdetail/pid/3895.html 山理工OJ
这道题的题意是先抛给你三个数n, T, w. 分别代表n行信息, 总时间, 要求地点,接下来是n行(x, c)为在地点x有c个烟花要爆炸
求的是最后在点w有多少个烟花~(烟花爆炸分开向左右移动的速度是每秒一单位,问樱花下落的速度是多少)
开始觉得这题有点像暴力(怎么最近看题都像暴力,emmm),直接建结构体存储(xi, ci),对于每一行操作一发,然后发现需要事先打表找一下每秒爆炸后的烟花数目分布规律。然后发现这个是个空位补0的杨辉三角,再加上题目中还要膜一下,就直接上Lucas定理好了,注意一下0的位置,找一找规律就好了。
AC代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long LL;
const LL MOD = 1000000007;
LL PowMod(LL a, LL b, LL MOD){
LL ret=1;
while(b){
if(b&1)
ret = (ret * a) % MOD;
a = (a*a) % MOD;
b >>= 1;
}
return ret;
}
LL fac[100005];
void Get_Fact()
{
int p = 100005;
fac[0] = 1;
for(LL i = 1;i <= p; i++)
fac[i] = (fac[i-1] * i) % MOD; //预处理阶乘
}
LL Lucas(LL n,LL m,LL p)
{
LL ret = 1;
while(n && m){
LL a = n%p, b = m%p;
if(a<b)
return 0;
ret = (ret * fac[a] * PowMod(fac[b] * fac[a-b] % p, p-2, p)) % p;
n /= p;
m /= p;
}
return ret;
}
int main()
{
Get_Fact();
int n, T, w;
while(~scanf("%d %d %d", &n, &T, &w)){
LL ans = 0;
for(int i = 0; i < n; i++){
int x, c;
scanf("%d %d", &x, &c);
int h = (int)abs(x-w);
if((h&1) == (T&1) && h <= T){
ans = (ans + c*Lucas(T, (h+T)/2, MOD)) % MOD;
}
}
ans %= MOD;
cout << ans << '\n';
}
return 0;
}