列表

详情


NC20102. [HNOI2013]数列

描述

小T最近在学着买股票,他得到内部消息:F公司的股票将会疯涨。股票每天的价格已知是正整数,并且由于客观上的原因,最多只能为N。
在疯涨的K天中小T观察到:除第一天外每天的股价都比前一天高,且高出的价格(即当天的股价与前一天的股价之差)不会超过M,M为正整数。
并且这些参数满足M(K-1) < N。 小T忘记了这K天每天的具体股价了,他现在想知道这K天的股价有多少种可能

输入描述

只有一行用空格隔开的四个数: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

说明:

【样例解释】
输出样例的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}

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

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;
}

上一题