NC20102. [HNOI2013]数列
描述
输入描述
只有一行用空格隔开的四个数:N、K、M、P。对P的说明参见后面“输出格式”中对P的解释。输入保证20%的数据M,N,K,P ≤ 20000,保证100%的数据M,K,P ≤ 109,N ≤ 1018 。
输出描述
仅包含一个数,表示这K天的股价的可能种数对于P的模值。
示例1
输入:
7 3 2 997
输出:
16
说明:
【样例解释】C++14(g++5.4) 解法, 执行用时: 4ms, 内存消耗: 480K, 提交时间: 2019-09-03 20:27:54
#include <bits/stdc++.h> using namespace std; typedef long long ll; ll n,k,m,p; ll qpow(ll a,ll n,ll mod){ ll ans = 1; while(n){ if(n & 1) ans = ans * a % mod; a = a * a % mod; n >>= 1; } return ans; } int main(){ cin>>n>>k>>m>>p; n %= p; ll ans1 = n * qpow(m,k - 1,p) % p; ll ans2 = (qpow(m,k - 2,p) * ((m * (m + 1) / 2) % p)) % p; ans2 = (k - 1) * ans2 % p; cout<<(ans1 - ans2 + p) % p<<endl; return 0; }
C++11(clang++ 3.9) 解法, 执行用时: 5ms, 内存消耗: 464K, 提交时间: 2019-11-01 19:11:38
#include<bits/stdc++.h> #define ll long long using namespace std; inline ll gg(ll a,ll b,ll p){ ll ret=1; while(b){ if(b&1)ret=(ret*a)%p; a=(a*a)%p;b>>=1; } return ret; } ll n,k,m,p,ans; int main(){ scanf("%lld%lld%lld%lld",&n,&k,&m,&p);n%=p; ans=n*gg(m,k-1,p)%p; ans-=gg(m,k-2,p)*(k-1)%p*(m*(m+1)/2%p)%p; printf("%lld",(ans+p)%p); return 0; }