BZOJ 4798: [Ceoi2015]Calvinball championship

Description

将所有人分组,每个组的编号是这个组中名字字典序最小的人的排名,将所有人名字按字典序排名后,求这是第几大的序列。

Solution

DP.

\(f[i][j][0/1]\)表示当前第\(i\)位,最高位为\(j\),是否顶格...

转移跟数位DP差不多...

因为我一开始把极限写成了\(mx\)...WA...

没滚数组...MLE...

取模太多被卡常...TLE...

新人求助,本地AC提交TLE...我发现本地\(0.2s 10^8\)

我也很绝望啊...

Code

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int N = 10050;
const int p = 1000007;

inline void Add(int &x,LL y) { x=(x+y)%p; }

int n,mx,cur;
int a[N];
int f[2][N][2];

int main() {
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	cur=mx=f[1][1][1]=1;
	for(int i=2;i<=n;i++) {
		cur^=1;
		for(int j=1;j<=i;j++) {
			f[cur][j][0]=f[cur][j][1]=0;
			Add(f[cur][j][0],(LL)f[cur^1][j][0]*j%p+f[cur^1][j-1][0]);
			if(j==mx) Add(f[cur][j][0],f[cur^1][j][1]*(a[i]-1));
		}mx=max(mx,a[i]),f[cur][mx][1]=1;
//		for(int j=1;j<=n;j++) printf("%d,%d%c",f[cur][j][0],f[cur][j][1]," \n"[j==n]);
	}
	int ans=0;
	for(int i=1;i<=n;i++) Add(ans,f[cur][i][0]);
	printf("%d\n",(ans+1)%p);
	return 0;
}

  

时间: 2024-10-26 11:45:12

BZOJ 4798: [Ceoi2015]Calvinball championship的相关文章

【bzoj4800】: [Ceoi2015]Ice Hockey World Championship dfs

[bzoj4800]: [Ceoi2015]Ice Hockey World Championship N<=40所以如果直接dfs背包会TLE 考虑Meet-in-the-middle 如果把N个物品分成前后A B两段分别背包 分别在A B中可行的方案的花费记录在a b中 答案就是a[i]+b[j]<=M的个数 把a b排序 然后序列就是单调的了 两个指针扫一遍就好了 1 #include <cstdlib> 2 #include <cstring> 3 #inclu

【BZOJ4800】 [Ceoi2015]Ice Hockey World Championship

4800: [Ceoi2015]Ice Hockey World Championship Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 68  Solved: 30[Submit][Status][Discuss] Description 有n个物品,m块钱,给定每个物品的价格,求买物品的方案数. Input 第一行两个数n,m代表物品数量及钱数 第二行n个数,代表每个物品的价格 n<=40,m<=10^18 Output 一行一个数表示购买

[bzoj4800][Ceoi2015]Ice Hockey World Championship

来自FallDream的博客,未经允许,请勿转载,谢谢. 有n个物品,m块钱,给定每个物品的价格,求买物品的方案数 n<=40 m<=10^18 考虑双向宽搜,然后得到两个大小为2^20的数组,排序之后两个指针推一推计算答案即可. 排序最好用基数排序 #include<iostream> #include<cstdio> #include<cstring> #define MN 40 #define MM 1050000 #define N 32767 #d

【bzoj4800】[Ceoi2015]Ice Hockey World Championship 折半搜索

题目描述 有n个物品,m块钱,给定每个物品的价格,求买物品的方案数. 输入 第一行两个数n,m代表物品数量及钱数 第二行n个数,代表每个物品的价格 n<=40,m<=10^18 输出 一行一个数表示购买的方案数 (想怎么买就怎么买,当然不买也算一种) 样例输入 5 1000 100 1500 500 500 1000 样例输出 8 题解 裸的折半搜索meet-in-the-middle 由于直接爆搜肯定会TLE,考虑把整个序列分成左右两部分,对于每部分求出它所有可以消耗钱数的方案.然后考虑左右

[Ceoi2015]Ice Hockey World Championship

有n个物品,m块钱,给定每个物品的价格,求买物品的方案数. n<=40,m<=10^18 水题,meet in the middle裸题,随便搞搞,统计答案二分一下就没了 #include<cstdio> #include<algorithm> int n,sum;long long m,f[1500001],a[41],ans; void dfs(int x,long long now){ if(x>n/2){f[++sum]=now;return ;} dfs

BZOJ 1013: [JSOI2008]球形空间产生器sphere

二次联通门 : BZOJ 1013: [JSOI2008]球形空间产生器sphere /* BZOJ 1013: [JSOI2008]球形空间产生器sphere 高斯消元 QAQ SB的我也能终于能秒题了啊 设球心的坐标为(x,y,z...) 那么就可以列n+1个方程,化化式子高斯消元即可 */ #include <cstdio> #include <iostream> #include <cstring> #define rg register #define Max

bzoj 3309 DZY Loves Math - 莫比乌斯反演 - 线性筛

对于正整数n,定义f(n)为n所含质因子的最大幂指数.例如f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0. 给定正整数a,b,求sigma(sigma(f(gcd(i,j)))) (i=1..a, j=1..b). Input 第一行一个数T,表示询问数. 接下来T行,每行两个数a,b,表示一个询问. Output 对于每一个询问,输出一行一个非负整数作为回答. Sample Input 4 7558588 9653114 6514903 445

【BZOJ】[HNOI2009]有趣的数列

[算法]Catalan数 [题解] 学了卡特兰数就会啦>_<! 因为奇偶各自递增,所以确定了奇偶各自的数字后排列唯一. 那么就是给2n个数分奇偶了,是不是有点像入栈出栈序呢. 将做偶数标为-1,做奇数标为+1,显然当偶数多于奇数时不合法,因为它压不住后面的奇数. 然后其实这种题目,打表就可知啦--QAQ 然后问题就是求1/(n+1)*C(2n,n)%p了,p不一定是素数. 参考bzoj礼物的解法. 看到网上清一色的素数筛+分解质因数解法,不解了好久,感觉写了假的礼物-- 后来觉得礼物的做法才比

洛谷 P2709 BZOJ 3781 小B的询问

题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数.小B请你帮助他回答询问. 输入输出格式 输入格式: 第一行,三个整数N.M.K. 第二行,N个整数,表示小B的序列. 接下来的M行,每行两个整数L.R. 输出格式: M行,每行一个整数,其中第i行的整数表示第i个询问的答案. 输入输出样例 输入样例#1: 6 4 3 1 3 2 1 1 3