codeforces#326-D - Duff in Beach- dp+分块
来源:互联网 发布:数据库代理 编辑:程序博客网 时间:2024/06/05 03:35
http://codeforces.com/contest/588/problem/D
题意给你 n, l and k (1 ≤ n, k, n × k ≤ 1^6 and 1 ≤ l ≤ 10^18).
给你n个数的数组a
然后 b数组就是 长度为l 由a数组不断重复拼接得到的数组
要你 从中选择一段合法子序列,求合法子序列的总数
条件如下:
1.这个序列的长度大于等于1,小于等于k
2.这个序列在每一个块中只能选择一个数,并且都必须选择在连续的块中
3.这个序列是非递减的
题解:
tm原始数据排序后得到的数组
dp[i][j] 表示//dp[i][j]表示 tm[i]结尾的长度为j的方案数
考虑到n,k的范围,我们不能直接开数组。。就用个vector吧
//用vector来存dp, vector[i][j]表示 tm[i]结尾的长度为j的方案数
考虑转移方程
对与当前长度为j的方案数 时:
{
以第i个数为结尾,长度为j 的方案数 = (所有比tm[i]小的数) 的长度为j-1 的方案数之和
}
for 一遍 o(n)就得到了长度为j 的方案数 了,然后 再对j for一遍, o(n*k)得到所有方案数
****************************
然后 提供的最多可选择的块数 是len= l/n 块
我们选择 长度为 j 的子序列时, 因为每块选一个数,并且要选的必须是连续的块
显然 我们只有 len-j+1种 选法,并且每种选法都是合法的
所以
for (i=1;i<=l/n&&i<=k;i++)//因为必须选择连续的块,总共有l/n个块,所以可以选连续i个块 的方案数为 l/n-i+1
{
ans+=(l/n-i+1)%mod*sum[i]; //注意l/n-i+1要先mod一下,防止乘法溢出
ans%=mod;
}
最后 对 最后一段判断一下是否有 多出l%n,暴力判断一下就好了
#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <algorithm>#include <iostream>#include <queue>#include <map>#include <set>#include <vector>using namespace std; __int64 tm[1000005];//排序后的数组__int64 sum[1000005];//长度为i的总方案数__int64 bb[1000005];//原始数组__int64 max(__int64 a,__int64 b){return a<b?b:a;}const __int64 mod= 1000000007;vector <__int64> sb[1000005];//用vector来存dp, vector[i][j]表示 tm[i]结尾的长度为j的方案数map<__int64,__int64> up;//映射原始数组和排序数组int main(){ __int64 n;__int64 i,j;__int64 l,k;scanf("%I64d%I64d%I64d",&n,&l,&k);for (i=1;i<=n;i++){scanf("%I64d",&tm[i]);bb[i]=tm[i];}sort(tm+1,tm+1+n);for (i=1;i<=n;i++)up[tm[i]]=i;for (i=1;i<=n;i++){sb[i].push_back(0);//去掉第一个位置,从1开始sb[i].push_back(1);}for (j=2;j<=k;j++){__int64 tot=1;for (i=1;i<=n;i++){__int64 p=upper_bound(tm+1,tm+1+n,tm[i])-(tm+1);//找到比tm[i]小的个数while(tot<=p){sum[j-1]+= sb[tot][j-1];//所有比tm[i]小的数的长度为j-1的方案,加上tm[i],就得到了以tm[i]结尾长度为j的方案数了 sum[j-1]%=mod;tot++;}sb[i].push_back(sum[j-1]);//把得到的结果存入 tm[i]结尾长度为j的 dp位置中}}for (i=1;i<=n;i++)//求一下sum[k]:长度为k的总方案数{sum[k]+=sb[i][k];sum[k]%=mod;} __int64 ans=0;for (i=1;i<=l/n&&i<=k;i++)//因为必须选择连续的块,总共有l/n个块,所以可以选连续i个块 的方案数为 l/n-i+1{ans+=(l/n-i+1)%mod*sum[i]; //注意l/n-i+1要先mod一下,防止乘法溢出ans%=mod;}if (l%n)//如果最后有剩余不完整的一小段,则对以该 数结尾的 所有长度小于k的方案数 都要加上一个 dp[i][len]: len=[1,k]{for (i=1;i<=l%n;i++){for (j=1;j<=k&&j<=(l/n+1);j++){__int64 idx= up[bb[i]];ans+=sb[idx][j];ans%=mod;}}}printf("%I64d\n",ans); return 0;}
- codeforces#326-D - Duff in Beach- dp+分块
- codeforces #326 D. Duff in Beach (dp)
- Codeforces 588D Duff in Beach 【离散化 + dp】
- Codeforces Round #326 (Div. 2) D. Duff in Beach
- codeforces 587B Duff in Beach (dp)
- Codeforces Round #326 (Div. 2) D. Duff in Beach(LIS)
- 【Codeforces Round 326 (Div 2)D】【DP】Duff in Beach 数列重复取数最多k次使得单调不下降
- Codeforces Round #326 (Div. 1) B Duff in Beach
- Codeforces Round #326 (Div. 1)-B. Duff in Beach
- Codeforces 587B Duff in Beach
- codeforces 587 B. Duff in Beach
- codeforces587B Duff in Beach
- codeforces#326-B-Duff in Love-暴力
- Codeforces 487D. Conveyor Belts 分块+DP
- codeforces 553 D Nudist Beach
- [二分答案 2-SAT验证 前后缀优化建图] Codeforces 587D #326 (Div. 1) D. Duff in Mafia
- codeforces 553D Nudist Beach 二分+bfs
- Codeforces Round #326 (Div. 2)B. Duff in Love
- Java中的关键字
- <草稿>Mac下配置JDK,Tomcat,Eclipse
- 第四周--项目5猴子选大王
- 代码小片段
- POJ 3250:Bad Hair Day 好玩的单调栈
- codeforces#326-D - Duff in Beach- dp+分块
- IOS学习笔记 - NSFileManager,沙盒路径,NSString类路径处理,NSCache,读取文件头判断图片类型
- html中charset和content-language的区别
- Android Studio 常用快捷键 windows下默认
- 湖北民族学院2015CSDN俱乐部招新
- 黑马程序员_反射
- KMP详解
- 全面解析Linux数字文件权限
- Eclipse背景颜色修改