The Battle of Chibi

Cao Cao made up a big army and was going to invade the whole South China. Yu Zhou was worried about it. He thought the only way to beat Cao Cao is to have a spy in Cao Cao’s army. But all generals and soldiers of Cao Cao were loyal, it’s impossible to convince any of them to betray Cao Cao. So there is only one way left for Yu Zhou, send someone to fake surrender Cao Cao. Gai Huang was selected for this important mission. However, Cao Cao was not easy to believe others, so Gai Huang must leak some important information to Cao Cao before surrendering. Yu Zhou discussed with Gai Huang and worked out N information to be leaked, in happening order. Each of the information was estimated to has ai value in Cao Cao’s opinion. Actually, if you leak information with strict increasing value could accelerate making Cao Cao believe you. So Gai Huang decided to leak exact M information with strict increasing value in happening order. In other words, Gai Huang will not change the order of the N information and just select M of them. Find out how many ways Gai Huang could do this.

Input

The first line of the input gives the number of test cases, T (1 ≤ 100). T test cases follow. Each test case begins with two numbers \(N (1 ≤ N ≤ 10^3 )\) and \(M (1 ≤ M ≤ N)\), indicating the number of information and number of information Gai Huang will select. Then N numbers in a line, the i-th number \(a_i (1 ≤ a_i ≤ 10^9 )\) indicates the value in Cao Cao’s opinion of the i-th information in happening order.

Output

For each test case, output one line containing ‘Case #x: y’, where x is the test case number (starting from 1) and y is the ways Gai Huang can select the information. The result is too large, and you need to output the result mod by 1000000007 \((10^9 + 7)\). Note: In the first case, Gai Huang need to leak 2 information out of 3. He could leak any 2 information as all the information value are in increasing order. In the second case, Gai Huang has no choice as selecting any 2 information is not in increasing order.

Sample Input

2

3 2

1 2 3

3 2

3 2 1

Sample Output

Case #1: 3

Case #2: 0

题意

给定一个长度为\(N\)的数列A,求A有多少个长度为M的严格递增子序列。输出对\(10^9+7\)取模后的结果。

暴力程序还是比较好写的,\(dp[i][j]\)表示到第\(i\)个数,长度为\(j\)的序列的个数。

转移也很好写:

\(dp[i][j]=\sum dp[k][j-1]\) \((k<i\) && \(a[k]<a[i])\)

时间复杂度:\(O(N^2M)\)

#include<bits/stdc++.h>
using namespace std;
int read()
{
int x=0,w=1;char ch=getchar();
while(ch>'9'||ch<'0') {if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*w;
}
const int N=1010;
int n,m,mod=1e9+7,ans;
int a[N],dp[N][N];
int main()
{
int t=read();
for(int w=1;w<=t;w++)
{
memset(dp,0,sizeof(dp));ans=0;
n=read();m=read();
for(int i=1;i<=n;i++) a[i]=read();
dp[0][0]=1;a[0]=-1;
for(int k=1;k<=m;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<i;j++)
{
if(a[i]>a[j])
dp[i][k]=(dp[i][k]+dp[j][k-1])%mod;
}
}
}
for(int i=m;i<=n;i++) ans=(ans+dp[i][m])%mod;
printf("Case #%d: %d\n",w,ans);
}
}

考虑如何对暴力算法进行优化。

由于状态的定义,前两重循环无法优化,所以我们对决策的选择上进行优化,将\(k\)视为定值,每当\(i\)增大\(1\),决策候选集合会增加一个元素\(dp[i][k-1]\),它可能对\([i+1,n]\)的决策作出贡献。我们需要维护一个决策集合,这个决策集合以\(a[i]\)为关键码,\(dp[i][k-1]\)为权值,那么这道题就转化为了一个支持插入和查询前缀和的问题。

于是我们可以对\(a\)数组进行离散化,通过树状数组维护前缀和。

时间复杂度:\(O(NMlogN)\)

注意:

1.树状数组不能处理0位置,需要整体往后移一位,在\(1\)~\(n+1\)上建树状数组。

2.关于线段树,它被卡常辣qwq

#include<bits/stdc++.h>
#define ll(x) (x<<1)
#define rr(x) (x<<1|1)
using namespace std;
int read()
{
int x=0,w=1;char ch=getchar();
while(ch>'9'||ch<'0') {if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*w;
}
const int N=1010;
int n,m,mod=1e9+7,ans;
int dp[N][N],c[N],pos[N];
struct node{
int v,id;
}a[N];
bool cmp(node p,node q){return p.v<q.v;}
int lowbit(int x){return x&(-x);}
void add(int p,int v)
{
for(int i=p;i<=n;i+=lowbit(i))
c[i]=(c[i]+v)%mod;
}
int query(int x)
{
int sum=0;
for(int i=x;i>0;i-=lowbit(i))
sum=(sum+c[i])%mod;
return sum;
}
int main()
{
int t=read();
for(int w=1;w<=t;w++)
{
memset(dp,0,sizeof(dp));ans=0;
n=read();m=read();n++;
for(int i=2;i<=n;i++) a[i].v=read(),a[i].id=i;
sort(a+2,a+n+1,cmp);
for(int i=2;i<=n;i++) pos[a[i].id]=i;pos[1]=1;
add(1,1);
for(int k=1;k<=m;k++)
{
for(int i=2;i<=n;i++)
{
dp[i][k]+=query(pos[i]);dp[i][k]%=mod;
add(pos[i],dp[i][k-1]);
}
memset(c,0,sizeof(c));
}
for(int i=m+1;i<=n;i++) ans=(ans+dp[i][m])%mod;
printf("Case #%d: %d\n",w,ans);
}
}

The Battle of Chibi(数据结构优化dp,树状数组)的更多相关文章

  1. $HDOJ5542\ The\ Battle\ of\ Chibi$ 数据结构优化$DP$

    $AcWing$ $Description$ $Sol$ 首先显然是是以严格递增子序列的长度为阶段,由于要单调递增,所以还要记录最后一位的数值 $F[i][j]$表示前$i$个数中以$A_i$结尾的长 ...

  2. NOI.AC#2139-选择【斜率优化dp,树状数组】

    正题 题目链接:http://noi.ac/problem/2139 题目大意 给出\(n\)个数字的序列\(a_i\).然后选出一个不降子序列最大化子序列的\(a_i\)和减去没有任何一个数被选中的 ...

  3. ACM学习历程—UESTC 1217 The Battle of Chibi(递推 && 树状数组)(2015CCPC C)

    题目链接:http://acm.uestc.edu.cn/#/problem/show/1217 题目大意就是求一个序列里面长度为m的递增子序列的个数. 首先可以列出一个递推式p(len, i) =  ...

  4. 奶牛抗议 DP 树状数组

    奶牛抗议 DP 树状数组 USACO的题太猛了 容易想到\(DP\),设\(f[i]\)表示为在第\(i\)位时方案数,转移方程: \[ f[i]=\sum f[j]\;(j< i,sum[i] ...

  5. 树形DP+树状数组 HDU 5877 Weak Pair

    //树形DP+树状数组 HDU 5877 Weak Pair // 思路:用树状数组每次加k/a[i],每个节点ans+=Sum(a[i]) 表示每次加大于等于a[i]的值 // 这道题要离散化 #i ...

  6. bzoj 1264 [AHOI2006]基因匹配Match(DP+树状数组)

    1264: [AHOI2006]基因匹配Match Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 793  Solved: 503[Submit][S ...

  7. 【bzoj2274】[Usaco2011 Feb]Generic Cow Protests dp+树状数组

    题目描述 Farmer John's N (1 <= N <= 100,000) cows are lined up in a row andnumbered 1..N. The cows ...

  8. 2015南阳CCPC C - The Battle of Chibi DP树状数组优化

    C - The Battle of Chibi Description Cao Cao made up a big army and was going to invade the whole Sou ...

  9. ccpc_南阳 C The Battle of chibi dp + 树状数组

    题意:给你一个n个数的序列,要求从中找出含m个数的严格递增子序列,求能找出多少种不同的方案 dp[i][j]表示以第i个数结尾,形成的严格递增子序列长度为j的方案数 那么最终的答案应该就是sigma( ...

  10. Codeforces 909 C. Python Indentation (DP+树状数组优化)

    题目链接:Python Indentation 题意: Python是没有大括号来标明语句块的,而是用严格的缩进来体现.现在有一种简化版的Python,只有两种语句: (1)'s'语句:Simple ...

随机推荐

  1. nginx利用try_files实现多个源

    比如一个视频网站,视频资源分散在几台机器上,但是给用要提供统一的IP,路径,端口.就需要nginx,先检查本机是否有改文件,如果没有就代理其他地方 location / { root /data/ww ...

  2. 双三次插值C代码(利用opencv)

    双三次插值C代码(利用opencv) phasecubic2.cpp D:\文件及下载相关\文档\Visual Studio 2010\Projects\phasecubic2\phasecubic2 ...

  3. Unity3D 可空值类型 Nullable

    值类型的变量永远不会变null,因为值类型是其本身不会变成null.引用类型可变成null,内存会全部使用0来表示null,因为这种开销会降低,仅仅需要将一块内存清除. 表示一些空值的方案: 1.使用 ...

  4. 【MyBatis】----【MyBatis】--封装---别名---properties

    一.核心配置文件 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration ...

  5. SSTap | ProxyCap

    SSTap  SSTap 全称 SOCKSTap, 是一款利用虚拟网卡技术在网络层实现的代理工具.SSTap 能在网络层拦截所有连接并转发给 HTTP, SOCKS4/5, SHADOWSOCKS(R ...

  6. paramiko远程连接linux服务器进行上传下载文件

    花了不少时间来研究paramiko中sftpclient的文件传输,一顿操作猛如虎,最后就一直卡在了路径报错问题,疯狂查阅资料借鉴大佬们的心得,还是搞不好,睡了个午觉醒来,仔细一看原来是指定路径的文件 ...

  7. Java——ArrayList源码解析

    以下针对JDK 1.8版本中的ArrayList进行分析. 概述     ArrayList基于List接口实现的大小可变的数组.其实现了所有可选的List操作,并且元素允许为任意类型,包括null元 ...

  8. 20191118 Spring Boot官方文档学习(4.8)

    4.8. RSocket RSocket参考 RSocket是用于字节流传输的二进制协议.它通过单个连接传递的异步消息来启用对称交互模型. Spring框架的spring-messaging模块在客户 ...

  9. Canvas入门08-绘制仪表盘

    需求 实现下图所示的仪表盘的绘制. 分析 我们先来将仪表盘进行图形拆分,并定义尺寸. 我们绘制的逻辑: 绘制中心圆 绘制环外圈圆 绘制环内圈圆 绘制刻度内圈圆 绘制刻度线 绘制刻度文字 绘制指针 定义 ...

  10. Mybatis—动态sql拼接问题

    背景:使用Mybatis的最近半年,经常发现一些小坑,现在总结回顾下,记个小本本,不让它再来欺负我! 百度了许久,才留心到官网文档,比我的全,我很菜的! *************<if> ...