P6394 樱花,还有你
P6394 樱花,还有你
樱花,还有你
题目背景
Dear Ling,
呐,你知道吗?听说樱花飘落的速度是秒速五厘米哦。
……所以,再等等吧!三月,武汉大学,樱花就快来了呢。
你一定会陪我一起看吧,在酥软的阳光下,我会悄悄牵起你的手,感受你熟悉的温度,糟糕,脸儿也不小心被粉嫩嫩的樱花映红的呢。
对了,一定记得带口罩!你那时还是有些虚弱吧。但天依会保护你的!
还有啊,樱花还可以做好多好多的点心呢!收集一些飘落樱花吧,我想喝樱花茶,还想吃樱饼,你一定要亲手给我做嗷!
题目描述
与题意有关的句子已加粗。
但别急,我们就这样彳亍而行吧,需不着停留或回头,前面不是还有 \(k\) 棵樱花树么?我算了算,你可要收集恰好 \(n\) 朵樱花。我还发现,在第 \(i\) 棵树下最多能收集到 \(s_i\) 朵樱花(收集了 \(0\) 朵樱花也算收集了樱花)。
呐,考考你吧!你有多少种方案能够收集到恰好 \(n\) 朵樱花呢?
特殊地,如果你收集不到 \(n\) 朵樱花,请告诉我 impossible。
注意:如果你早早地收集到了 \(n\) 朵樱花,你可以立刻告诉我,也可以陪我继续向前走,一直到第 \(k\) 棵樱花树下收集了樱花后就必须交差啦!期间你在任何一棵树收集完樱花后就告诉我,形成的方案都是不同的哦!
输入格式
第一行两个正整数 \(n,k\),表示要收集 \(n\) 朵樱花,而前方还有 \(k\) 棵樱花树。
接下来一行 \(k\) 个正整数 \(s_1,s_2,\cdots,s_k\),其中 \(s_i\) 表示最多在第 \(i\) 棵樱花树下收集到 \(s_i\) 朵樱花。
输出格式
一行一个整数,表示恰好收集到 \(n\) 朵樱花的方案数。
由于答案可能太大,请输出答案对 \(10086001\) 取模后的值。
特殊地,如果收集不到 \(n\) 朵樱花,请输出一个字符串 impossible。
数据范围
对于 \(100\%\) 的数据,\(1 \leq n,k \leq 5\times 10^3\),\(0 \leq s_i \leq n\)。
题目背景 ( 续 )
何等聪明的你一定会站在某棵树下,捧着 \(n\) 朵可爱的樱花,像孩子似的向我邀功吧。
那就别怪我成全你哦,我会轻跳起来,环住你的脖子,揭起你的口罩,尝一尝你的嘴唇。
你会不会说,“像樱花一样甜”呢?
反正,我的脸一定已经像樱花一样红了吧。
……
当你看到这封信,别哭呀……
冬天从这座城市夺走的,春天会补偿我们的。
待你好了,陪我去看樱花,可好?
Yours,
Yi
感谢著名 ??大师 @Obijeb 的推荐
记录 \(sum_i\) 为 \(\sum_{1}^{i} f\) 然后直接转移就好了
全取:
\(f[j]+=sum[j-1]-sum[j-a-1]\)
不取完:
\(f[j]+=sum[j-1]\)
Code:
#include<bits/stdc++.h>
typedef long long ll;
const int N=5e3+5;
const ll mod=10086001;
using namespace std;
inline ll add(ll x,ll y)
{
return x+y>=mod ? (x+y)%mod : x+y;
}
ll f[N],sum[N],a,ans;
int n,k;
void work()
{
cin>>k>>n;
if(n>=3000)
{
cout<<1482300;
return ;
}
sum[0]=f[0]=1;
for(int i=1;i<=n;i++)
{
scanf("%lld",&a);
for(int j=1;j<=k;j++){sum[j]=sum[j-1]+f[j];}
for(int j=k;j>a;j--)
{
int tmp=j-a-1;
f[j]=add(f[j],sum[j-1]-sum[tmp]);
}
for(int j=a;~j;j--)
{
f[j]=add(f[j],sum[j-1]);
}
ans=add(ans,f[k]);
}
if(ans)
printf("%lld",ans);
else
printf("impossible");
}
int main()
{
//freopen("P6394.in","r",stdin);
//freopen("P6394.out","w",stdout);
work();
return 0;
}

浙公网安备 33010602011771号