【HNOI2013】数列
2015-12-13 18:41
176 查看
题目
小T最近在学着买股票,他得到内部消息:F公司的股票将会疯涨。股票每天的价格已知是正整数,并且由于客观上的原因,最多只能为N。在疯涨的K天中小T观察到:除第一天外每天的股价都比前一天高,且高出的价格(即当天的股价与前一天的股价之差)不会超过M,M为正整数。并且这些参数满足M(K-1)
分析
我们发现若是从他们的各自股价开始入手,问题会变得很困难,为什么呢?因为股价本身就是一个递增的值,不方便我们讨论方案数
于是我们可以从有限定的m入手,即每两天之间股价的差:
a[1],a[2],a[3],a[4]..a[k-1]
那么这样就不用去管每个a[i]的值之间的关系了。
若是确定了这k-1个数,那么很明显会有n−∑a[i]n-\sum a[i]的方案(即第一天的股价的值)
那么总的方案就是∑n−∑a[i]\sum n-\sum a[i]
然而这样想上面的数列一共有mk−1m^{k-1},我们先提取n出来,就是n∗mk−1n*m^{k-1}
而a[i]我们可以这样处理,因为一共有mk−1m^{k-1}个数列,也就是有mk−1∗(k−1)m^{k-1}*(k-1)个数
而且每一个数的范围都是1..m,出现的次数都是一样的也就是mk−1∗(k−1)/m=mk−2∗(k−1)m^{k-1}*(k-1)/m=m^{k-2}*(k-1)
这样的话,用等差数列求和,每m个数配一组总的就是mk−2∗(k−1)∗(m+1)∗m/2m^{k-2}*(k-1)*(m+1)*m/2
所以答案就是n∗mk−1−mk−2∗(k−1)∗(m+1)∗m/2n*m^{k-1}-m^{k-2}*(k-1)*(m+1)*m/2
到此便很好的解决问题了。这题关键是转换成差来思考。
[code]#include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<cstdlib> #include<cstdio> using namespace std; long long ans,n,m,k,p; long long power(long long x,long long y,long long z){ if (y==1) return x; else { long long e=power(x,y>>1,z); e=(e*e)%p; if (y%2==1) e=(e*x)%p; return e; } } int main(){ scanf("%lld%d%d%d",&n,&k,&m,&p); n=n%p; ans=(power(m % p,k-1,p)*(n%p))%p; ans-=((power(m % p,k-2,p)*(k-1)% p)*(((m+1)*m/2)% p))%p; ans=(ans+p)%p; printf("%d",ans); }
相关文章推荐
- android如何使用自己定义JNI接口,以及NDK环境建设和使用的工具。
- 世界是数字的(其二)
- IOS开发音频播放之AVaudioplayer
- poj 2909
- OpenJudge_P4976 硬币(DP+数论+容斥原理)
- python闭包与装饰器
- js函数 Number()、parseInt()、parseFloat()的区别:
- 素数筛
- Fiddler 抓取手机APP数据包
- js事件机制
- Unicode字符列表(超完整)
- Linux进程间通信——使用信号量
- 支持向量机(2)
- 数据结构-Java实现-简单回文
- Tomcat server.xml配置示例
- activemq設置
- Lock锁的使用示例
- uva 1629——Cake slicing
- DIV+CSS用法
- 第15周项目2-用哈希表组织关键字