fireworks 2017年山东省ACM省赛C题 SDUT 3895 (逆元求组合数)
2017-07-23 20:30
417 查看
题目
Time Limit: 1000MS Memory Limit: 65536KB
Submit Statistic Discuss
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|≤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).
For each test case, you should output the answer MOD 1000000007.
题目 大意
有一种特殊的烟花,他每一秒可以向自己的左右两边分裂相同数量的烟花
求所给位置在T时间后有多少个烟花
要求输入n(烟花的数量),T(烟花的持续时间),w(所求的位置)
接下来n行每一行输入两个数xi(烟花的初始位置) ci(该点的烟花数量)
解题思路
我们假设在0的位置有一个烟花
下面这个图给出了在1,2,3,秒时,各个坐标点产生的烟花的数量(蓝色为烟花数量)
仔细观察我们就可以发现这是一个我们很熟悉的数学定理,杨辉三角
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
……………………
有了这个之后就很好办了,只要能确定C(n,m)其中的n和m就可以了
在这里我们可以看出来n就是题目中给出的T,
要求m需要略作思考,这里我们设一个temp代表所求位置到烟花的绝对值,这里我们以图为例子推演一下,假设所求位置是-1,时间限制是3秒,烟花的初始位置是0,那么两点之间的绝对值temp=1,我们可以发现这里我们要求的m=(T/2)-(temp/2),或者是m=(T+1/2)-(temp+1/2),严格来说第二种是准确的,但是因为这道题目,T和temp只有是同奇同偶的情况下才代表该点有烟花(大家可以对着图演示一下就会发现这个规律),因为同奇同偶导致了两个式子结果是一样的。
上面提到了同奇同偶,但是怎么来确定同奇同偶?我这里是设了两个变量tomd(代表T的奇偶性),temp(所求到烟花的绝对值,这里只需要对temp%2与tmod判等就可以验证是否是同奇同偶)。
这个题用到的主要算法是逆元组合数,用来求组合数的还有lucas,但是而这还有有区别的,逆元求组合数适用于数较小且mod较大时,还要保证mod必须为素数,lucas适用于数较大且mod较小时的组合数
这两个算法这里不展开细讲,要想深入学习,可以看一下其他大牛的讲解
fireworks
Time Limit: 1000MS Memory Limit: 65536KBSubmit Statistic Discuss
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.
Example Input
1 2 0 2 2 2 2 2 0 3 1 2
Example Output
2 3
题目 大意
有一种特殊的烟花,他每一秒可以向自己的左右两边分裂相同数量的烟花
求所给位置在T时间后有多少个烟花
要求输入n(烟花的数量),T(烟花的持续时间),w(所求的位置)
接下来n行每一行输入两个数xi(烟花的初始位置) ci(该点的烟花数量)
解题思路
我们假设在0的位置有一个烟花
下面这个图给出了在1,2,3,秒时,各个坐标点产生的烟花的数量(蓝色为烟花数量)
仔细观察我们就可以发现这是一个我们很熟悉的数学定理,杨辉三角
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
……………………
有了这个之后就很好办了,只要能确定C(n,m)其中的n和m就可以了
在这里我们可以看出来n就是题目中给出的T,
要求m需要略作思考,这里我们设一个temp代表所求位置到烟花的绝对值,这里我们以图为例子推演一下,假设所求位置是-1,时间限制是3秒,烟花的初始位置是0,那么两点之间的绝对值temp=1,我们可以发现这里我们要求的m=(T/2)-(temp/2),或者是m=(T+1/2)-(temp+1/2),严格来说第二种是准确的,但是因为这道题目,T和temp只有是同奇同偶的情况下才代表该点有烟花(大家可以对着图演示一下就会发现这个规律),因为同奇同偶导致了两个式子结果是一样的。
上面提到了同奇同偶,但是怎么来确定同奇同偶?我这里是设了两个变量tomd(代表T的奇偶性),temp(所求到烟花的绝对值,这里只需要对temp%2与tmod判等就可以验证是否是同奇同偶)。
这个题用到的主要算法是逆元组合数,用来求组合数的还有lucas,但是而这还有有区别的,逆元求组合数适用于数较小且mod较大时,还要保证mod必须为素数,lucas适用于数较大且mod较小时的组合数
这两个算法这里不展开细讲,要想深入学习,可以看一下其他大牛的讲解
#include<iostream> #include<cstdio> #include<cmath> using namespace std; #define LL long long const LL mod=1000000007; const LL fcnt=100005; LL xi; LL ci; LL fac[fcnt]; void getfac() { fac[0]=1; for(int i=1;i<fcnt;i++) fac[i]=fac[i-1]*i%mod; } LL quickpow(LL a,LL b) { if(b<0) return 0; LL ret =1; a%=mod; while(b) { if(b&1) ret =(ret*a)%mod; b>>=1; a=(a*a)%mod; } return ret; } LL inv(LL a) { return quickpow(a,mod-2); } LL C(LL n,LL m) { if(n<m) return 0; return fac *inv(fac[m])%mod*inv(fac[n-m])%mod; } int main() { LL n; LL T,p; getfac(); while(scanf("%lld%lld%lld",&n,&T,&p)!=EOF) { LL tmod=T%2; LL myans=0; for(int i=0;i<n;i++) { scanf("%lld%lld",&xi,&ci); LL temp=abs(xi-p); if(temp%2==tmod&&temp<=T) { myans=(myans+ci*C(T,(T+1)/2-(temp+1)/2))%mod; } } printf("%lld\n",myans); } return 0; }
相关文章推荐
- 2017年山东省第八届ACM大学生程序设计竞赛 C fireworks(sdut 3895) 逆元求组合数
- SDUT 3895 (山东省第八届ACM省赛C题) fireworks 杨辉三角+乘法逆元
- 第八届山东省赛 C sdut 3895 fireworks(组合数+逆元)
- Fireworks(山东省第8届ACM省赛)逆元,组合数
- 山东省第八届 ACM 省赛 fireworks (组合数+逆元)
- 2017山东省第八届ACM省赛 fireworks(杨辉三角 + 逆元)
- SDUT 3895 fireworks 山东第八届ACM大赛C题(组合数学(杨辉三角)+逆元)
- sdut 3895/第八届省赛C题 fireworks 杨辉三角 逆元求C(n,m)%mod
- HEX----组合数+逆元+思维 山东省第八届省赛D题
- Sdut 2164 Binomial Coeffcients (组合数学) (山东省ACM第二届省赛 D 题)
- Sdut 2108 Alice and Bob(数学题)(山东省ACM第四届省赛D题)
- sdut 2603 Rescue The Princess(算是解析几何吧)(山东省第四届ACM省赛A题)
- 山东省第一届ACM省赛 E SDUT 2155 Emergency(最短路)
- 山东省第一届ACM省赛 F SDUT 2156 Fairy tale
- sdut 2161 Simple Game(山东省第二届acm省赛A题)(博弈论Nim+Bush?)
- 山东省第一届ACM省赛 G SDUT 2157 Greatest Number(暴力枚举)
- 山东省第一届ACM省赛 C SDUT 2153 Clockwise(dp+计算几何)
- 2017年山东省第八届ACM大学生程序设计竞赛 B Quadrat(sdut 3894) 打表找规律
- 山东省第一届ACM省赛 H SDUT 2158 Hello World!(穷举)
- 山东省第一届ACM省赛 I SDUT 2159 Ivan comes again!(STL-set)