1 条题解
-
0
自动搬运
来自洛谷,原作者为

龙·海流
我很懒,什么也没有留下搬运于
2025-08-24 22:07:39,当前版本为作者最后更新于2019-06-16 09:42:24,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
观察代码部分可以发现ans=循环次数*f(q)
处理循环次数:
1.显然的一点是a[1]>a[2]>...>a[k],即从a[1]到a[k]严格单减,因为a[k]最小为1,所以a[1]最小为k,最大为n;
2.开始递推:
先举个例子,设n=7,k=4;
a1=4时,a2~a4分别为3,2,1;
a1=5时,a1~a4可能为,{4,3,2},{4,3,1},{4,2,1},{3,2,1},即从4,3,2,1中扔掉一个数,剩下的三个数即为a2~a4,方案数为C(4,1);
a1=6时,从5,4,3,2,1中选出两个数扔掉,剩下三个数即为a2~a4,方案数为C(5,2);
a1=7时,从6,5,4,3,2,1中选出三个数扔掉,剩下三个数即为a2~a4,方案数为C(6,3);
于是a1=4时的方案数可看做C(3,0);
所以方案数=C(3,0)+C(4,1)+C(5,2)+C(6,3)=C(7,4);
(以下是计算过程:
ans=C(3,0)+C(4,1)+C(5,2)+C(6,3)=C(4,0)+C(4,1)+C(5,2)+C(6,3)=C(5,1)+C(5,2)+C(6,3)=C(6,2)+C(6,3)=C(7,3)=C(7,4)
应用性质:C(n+1,m)=C(n,m)+C(n,m-1);)
所以对于给定的n与k: a1=k时,方案数C(k-1,0);
a1=k+1时,方案数C(k,1);
a1=k+2时,方案数C(k+1,2);
a1=k+3时,方案数C(k+2,3);
......
a1=n时,方案数为C(n-1,n-k);
(为啥这里是C(n-1,n-k),一共有n-1个元素,需要留下k-1个,所以需要扔掉(n-1)-(k-1)个元素,即扔掉n-k个元素)
所以方案总数=C(k-1,0)+C(k,1)+C(k+1,2)+...+C(n-1,n-k)=C(n,n-k)=C(n,k);
C(n,k)用阶乘求即可,卢卡斯在这里基本没用,因为n和k都小于1e9+7;当然,不要忘了求逆元;
然后就剩下f(q)了
暴力算乘方即使是快速幂都会很慢,但是这个式子可以通过提公因式转化一下;
还是先举个栗子:
f(q)=a3·x^3+a2·x^2+a1·x+a0 =(a3·x^2+a2·x+a1)·x+a0 =[(a3·x+a2)·x+a1]·x+a0其实这个就是著名的秦九韶(shao2)算法,代码实现在下文中会给出;
最后附上自己的代码
#include<iostream> #include<cstdio> #define ll long long using namespace std; const long long mod=1000000007; long long n,m,k,q,a[500010],ans; ll ksm(ll a,ll b) { ll ret=1; while(b) { if(b&1) ret=ret*a%mod; b>>=1; a=a*a%mod; } return ret; } ll C() { ll a=1,b=1; for(ll i=n;i>=n-k+1;--i) a=a*i%mod; for(ll i=2;i<=k;++i) b=b*i%mod; return a*ksm(b,mod-2)%mod; //根据费马小定理,若a与p互质,那么a%p的逆元就是a^p-2,所以用快速幂求a%p的逆元 } int main() { scanf("%lld%lld%lld%lld",&n,&m,&k,&q); q=q%mod;//不加这一句会少20分,很玄学 for(int i=0;i<=m;++i) scanf("%lld",&a[i]); //秦九韶算法 for(ll i=m;i>0;--i) ans=(ans+a[i])*q%mod; ans=(ans+a[0])%mod;//别忘了加上a0 ans=ans*C()%mod; printf("%lld",ans); return 0; }组合数见高中数学选修3-3
秦九韶算法见高中数学必修3
- 1
信息
- ID
- 2488
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者