打工
来源:互联网 发布:投标书编制软件 编辑:程序博客网 时间:2024/06/10 21:23
题目
样例输入:
第一行,一个整数N表示参赛人数。
第二行,N个整数,表示询问的分队方式的序列。
3
1 2 2
样例输出:
一行,一个整数表示这种方式会在第几天被采用。答案对1,000,007取模。
数据范围:
对于100%的数据,N ≤ 10000 , 数据保证询问的数列是一个有效的序列。
详细情况见下表。
剖解题目
。。。。。
思路
这题好坑啊。。。。。
比赛时想了一会儿,看了看30分好拿。
发现可以dp,但看到n<=10000,就觉得n^2肯定过不了,想了半天又觉得我的dp似乎是n^3,就没有动手打。
然后交了个暴力水了30分。QwQ.
解法
30%:暴力!
其他部分分就不说了。
100%:有顺推与逆推。
我们发现第i位后的方案数至于第i位后的长度以及前i位的最大值有关。
逆推(粗略提一下,我没打):设f[i,j]表示前i位已经匹配完,且最大的ai是j的方案数,那么就有f[i,j]=f[i+1,j]*j+f[i+1,j+1];
初始化是f[n][i]=1;
顺推:差不多,f[i][j]=f[i-1][j]*j+f[i-1][j-1];然后由于每一位都有a[i]的限制,不需要全部处理。每次dp完i,就对f[i][max(1~i-1)]+=a[i]-1;就不需要初始化了。
注意:由于空间限制,一般是要滚动f的第一维,但我偷了点懒,将所有计算都转化为longlong的形态,就没有开滚动。
代码
#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#define fo(i,a,b) for(int i=a;i<=b;i++)#define down(i,a,b) for(int i=a;i>=b;i--)#define ll long longusing namespace std;const int maxn=10005,mo=1e6+7;int f[maxn][maxn],n,a[maxn],c[maxn];int main(){// freopen("T.in","r",stdin); scanf("%d",&n); fo(i,1,n) { scanf("%d",&a[i]); c[i]=max(a[i],c[i-1]); //f[n][i]=1; } int ans=0; fo(i,2,n){ fo(j,1,i) f[i][j]=((ll)f[i-1][j]*(ll)j+(ll)f[i-1][j-1])%mo; f[i][c[i-1]]=((ll)f[i][c[i-1]]+(ll)a[i]-1)%mo; } fo(i,1,n) ans=((ll)ans+(ll)f[n][i])%mo; printf("%d",ans+1);}
0 0
- 打工
- 打工
- 打工
- 打工?
- 打工
- 打工
- 打工人生
- 打工联盟
- 打工曲
- IT打工
- 外出打工
- 打工的
- 打工去
- 打工心酸
- 打工者
- 打工vahnzjkl
- 【JZOJ1282】打工
- 【JZOJ4806】打工
- 记又一次unhappy考试(10.6)
- awk中可以使用system来执行复杂的shell命令
- 数组简单介绍
- 关于eSIM的一些简单介绍
- 棋盘问题(POJ1321)(A)
- 打工
- 关于打包成APK
- java--servlet相关类(4)
- 机房收费系统之上下机思路整理
- C语言位运算
- unity3d--物体移动方式总结
- Error和Exception的区别
- 稀疏表示之OMP,SOMP算法及openCV实现
- SQL 之 范式