山东省 第八届ACM省赛 C题--fireworks

贴一个题目链接: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;
}

猜你喜欢

转载自blog.csdn.net/water_zero_saber/article/details/80010773