[题解] BZOJ 3142 [HNOI2013]数列
2018-03-16 20:53
218 查看
题目描述 Description
小T最近在学着买股票,他得到内部消息:F公司的股票将会疯涨。
股票每天的价格已知是正整数,并且由于客观上的原因,最多只能为NN。在疯涨的KK天中小T观察到:除第一天外每天的股价都比前一天高,且高出的价格(即当天的股价与前一天的股价之差)不会超过MM,MM为正整数。并且这些参数满足M∗(K−1)<NM∗(K−1)<N。
小T忘记了这KK天每天的具体股价了,他现在想知道这KK天的股价有多少种可能。
输入描述 Input Description
输入文件只有一行用空格隔开的四个数:N,K,M,PN,K,M,P
输出描述 Output Description
仅包含一个数,表示这KK天的股价的可能种数对于P的模值
样例输入 Sample Input
7 3 2 997
样例输出 Sample Output
16
样例解释
输出样例的16表示输入样例的股价有16种可能:
{1,2,3},{1,2,4},{1,3,4},{1,3,5},
{2,3,4},{2,3,5},{2,4,5},{2,4,6},
{3,4,5},{3,4,6},{3,5,6},{3,5,7},
{4,5,6},{4,5,7},{4,6,7},{5,6,7}
数据范围及提示 Data Size & Hint
20%的数据M,N,K,P≤20000M,N,K,P≤20000
100%的数据K,M,P≤109,N≤1018K,M,P≤109,N≤1018
这个序列对于总数的贡献为1,当然,是当a[k]≤na[k]≤n的时候
显然的,维持每天上涨的价格不变,由于a[1]a[1]能够有多种取值,那么它就会有很多贡献,当然,变化后的a[1]a[1]仍然要保证a[k]≤na[k]≤n
那么能不能考虑维护一个股票价格的差分数列?就不用考虑a[1]a[1]的取值
并且,这个差分数列s[1],s[2],s[3],...,s[k−1]s[1],s[2],s[3],...,s[k−1]所做出的贡献就为n−∑k−1i=1s[i]n−∑i=1k−1s[i]
一共有mk−1mk−1个不同的差分数列,每个数列做出的贡献值为n−∑k−1i=1s[i]n−∑i=1k−1s[i]
那么总贡献就为
∑mk−1d=1(n−∑k−1i=1s[d][i])∑d=1mk−1(n−∑i=1k−1s[d][i])
将nn提出可得
n∗mk−1−∑mk−1d=1∑k−1i=1s[d][i]n∗mk−1−∑d=1mk−1∑i=1k−1s[d][i]
现在要做的就是处理后面那一堆东西
注意,ss显然是将所有可能的排列情况都算了进去,并且s[d][i]∈[1,m]s[d][i]∈[1,m]
那么后面一共就会有mk−1∗(k−1)mk−1∗(k−1)个数,并且在[1,m][1,m]中完全平均分布
所以[1,m][1,m]中的每个数都会出现mk−1∗(k−1)m=mk−2∗(k−1)mk−1∗(k−1)m=mk−2∗(k−1)次
运用小学数学知识,将其总和化为mk−2∗(k−1)∗(m+1)∗m2mk−2∗(k−1)∗(m+1)∗m2
这样就很好求解了
最终答案为n∗mk−1−mk−2∗(k−1)∗(m+1)∗m2n∗mk−1−mk−2∗(k−1)∗(m+1)∗m2
快速幂就好啦╮(╯_╰)╭
努力追赶dalao中
给予我力量吧(丢脸ing
代码如下
小T最近在学着买股票,他得到内部消息:F公司的股票将会疯涨。
股票每天的价格已知是正整数,并且由于客观上的原因,最多只能为NN。在疯涨的KK天中小T观察到:除第一天外每天的股价都比前一天高,且高出的价格(即当天的股价与前一天的股价之差)不会超过MM,MM为正整数。并且这些参数满足M∗(K−1)<NM∗(K−1)<N。
小T忘记了这KK天每天的具体股价了,他现在想知道这KK天的股价有多少种可能。
输入描述 Input Description
输入文件只有一行用空格隔开的四个数:N,K,M,PN,K,M,P
输出描述 Output Description
仅包含一个数,表示这KK天的股价的可能种数对于P的模值
样例输入 Sample Input
7 3 2 997
样例输出 Sample Output
16
样例解释
输出样例的16表示输入样例的股价有16种可能:
{1,2,3},{1,2,4},{1,3,4},{1,3,5},
{2,3,4},{2,3,5},{2,4,5},{2,4,6},
{3,4,5},{3,4,6},{3,5,6},{3,5,7},
{4,5,6},{4,5,7},{4,6,7},{5,6,7}
数据范围及提示 Data Size & Hint
20%的数据M,N,K,P≤20000M,N,K,P≤20000
100%的数据K,M,P≤109,N≤1018K,M,P≤109,N≤1018
Solution
将某一个确定的上涨序列a[1],a[2],a[3],...,a[k]a[1],a[2],a[3],...,a[k]写出来这个序列对于总数的贡献为1,当然,是当a[k]≤na[k]≤n的时候
显然的,维持每天上涨的价格不变,由于a[1]a[1]能够有多种取值,那么它就会有很多贡献,当然,变化后的a[1]a[1]仍然要保证a[k]≤na[k]≤n
那么能不能考虑维护一个股票价格的差分数列?就不用考虑a[1]a[1]的取值
并且,这个差分数列s[1],s[2],s[3],...,s[k−1]s[1],s[2],s[3],...,s[k−1]所做出的贡献就为n−∑k−1i=1s[i]n−∑i=1k−1s[i]
一共有mk−1mk−1个不同的差分数列,每个数列做出的贡献值为n−∑k−1i=1s[i]n−∑i=1k−1s[i]
那么总贡献就为
∑mk−1d=1(n−∑k−1i=1s[d][i])∑d=1mk−1(n−∑i=1k−1s[d][i])
将nn提出可得
n∗mk−1−∑mk−1d=1∑k−1i=1s[d][i]n∗mk−1−∑d=1mk−1∑i=1k−1s[d][i]
现在要做的就是处理后面那一堆东西
注意,ss显然是将所有可能的排列情况都算了进去,并且s[d][i]∈[1,m]s[d][i]∈[1,m]
那么后面一共就会有mk−1∗(k−1)mk−1∗(k−1)个数,并且在[1,m][1,m]中完全平均分布
所以[1,m][1,m]中的每个数都会出现mk−1∗(k−1)m=mk−2∗(k−1)mk−1∗(k−1)m=mk−2∗(k−1)次
运用小学数学知识,将其总和化为mk−2∗(k−1)∗(m+1)∗m2mk−2∗(k−1)∗(m+1)∗m2
这样就很好求解了
最终答案为n∗mk−1−mk−2∗(k−1)∗(m+1)∗m2n∗mk−1−mk−2∗(k−1)∗(m+1)∗m2
快速幂就好啦╮(╯_╰)╭
努力追赶dalao中
给予我力量吧(丢脸ing
代码如下
#include <bits/stdc++.h> using namespace std; #define ll long long ll n,k,m,p,ans; ll read() { ll ans=0,flag=1; char ch=getchar(); while((ch>'9' || ch<'0') && ch!='-') ch=getchar(); if(ch=='-') flag=-1,ch=getchar(); while(ch>='0' && ch<='9') ans=ans*10+ch-'0',ch=getchar(); return ans*flag; } ll qpow(ll a,ll b,ll mod) { ll ans=1; while(b>0) { if(b&1) {ans*=a;ans%=mod;} b>>=1;a*=a;a%=mod; } return ans; } ll exgcd(ll a,ll b,ll &x,ll &y) { if(b==0) {x=1;y=0;return a;} ll gcd=exgcd(b,a%b,x,y); ll t=x; x=y; y=t-(a/b)*y; } int main() { n=read(),k=read(),m=read(),p=read(); ll x,y,gcd; gcd=exgcd(2,p,x,y); x=(x%p+p)%p; ans+=(qpow(m,k-1,p)*(n%p))%p; ans-=((((qpow(m,k-1,p)*(k-1))%p*(m+1))%p)%p*x%p); ans=(ans%p+p)%p; printf("%lld\n",ans); return 0; }
相关文章推荐
- BZOJ3142: [Hnoi2013]数列
- BZOJ3142 HNOI2013数列(组合数学)
- bzoj3142 [Hnoi2013]数列
- BZOJ 3142: [Hnoi2013]数列
- BZOJ 3142 HNOI2013数列
- bzoj 3142: [Hnoi2013]数列 数学
- 【bzoj3142】[Hnoi2013]数列
- 【bzoj3142】[Hnoi2013]数列
- BZOJ3142 [Hnoi2013]数列
- bzoj 3142: [Hnoi2013]数列 组合
- 3142:[HNOI2013]数列 - BZOJ
- 【bzoj3142】【HNOI2013】【数列】【数学】
- BZOJ3142 [Hnoi2013]数列 (组合数学)
- [bzoj3142][HNOI2013]数列
- [BZOJ3142][HNOI2013]数列
- 数列 [Bzoj3142,Codevs2089,HNOI2013]
- [BZOJ3142][Hnoi2013]数列(差分+计数)
- bzoj 3142: [Hnoi2013]数列
- HNOI2013 BZOJ3142 数列
- 【bzoj3142】[Hnoi2013]数列 数学