湖南多校对抗赛(2015.03.15)9题题解 ABCEFGHJK

比赛链接:点击打开链接

A:点击打开链接

题意:

问n的排列中多少个不满足 for(int i = 1; i <= n; i++) a[a[i]] == a[i];

显然有 n!-1

所以输出 (n!-1)%mod;

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <vector>
using namespace std;

typedef long long ll;
const int N = 100005;
const int mod = 1e9+7;

template <class T>
inline bool rd(T &ret) {
	char c; int sgn;
	if(c=getchar(),c==EOF) return 0;
	while(c!='-'&&(c<'0'||c>'9')) c=getchar();
	sgn=(c=='-')?-1:1;
	ret=(c=='-')?0:(c-'0');
	while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
	ret*=sgn;
	return 1;
}
template <class T>
inline void pt(T x) {
    if (x <0) {
        putchar('-');
        x = -x;
    }
    if(x>9) pt(x/10);
    putchar(x%10+'0');
}
ll ans[N];
int main() {
	int T; rd(T);
	ans[1] = 1;
	for(ll i = 2; i < N; i++){
		ans[i] = ans[i-1]*i % mod;
	}
	int n;
	while(T--){
		rd(n);
		pt((ans[n]-1+mod)%mod); puts("");
	}

	return 0;
}

B:点击打开链接

题意:

给定n个点的有向图(1为起点,n为终点)

下面每两行给出一个点的出度和所连接的下一个点。

第n个点是没有出度的

图是这样的: 1->2, 1->3, 2->3

第一问:

若存在一种方案使得这个人进入一个点后再也不能到达终点则输出 PRISON , 否则输出 PARDON

第二问:

若这个人可以在图里走无穷步则输出UNLIMITED, 否则输出LIMITED

代码:点击打开链接

C:点击打开链接

双调旅行商

代码:点击打开链接

E:点击打开链接

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>

using namespace std;

const int MAX_N = 2000007;

int n;
int a[MAX_N];
long long s[MAX_N], t[MAX_N];

int main() {
	int T;
	scanf("%d", &T);
	while (T-- > 0) {
		scanf("%d", &n);
		for (int i = 1; i <= n; ++i) {
			scanf("%d", &a[i]);
		}
		int up = 2 * n;
		for (int i = n + 1; i <= up; ++i) {
			a[i] = a[i - n];
		}
		long long sum = 0, ans = 0, sum2 = 0;
		int id = 0;
		for (int i = 1; i <= n; ++i) {
			sum += a[i];
			sum2 += a[i];
			if (sum < 0) {
				sum = 0;
			}
			if (sum > ans) {
				ans = sum;
				id = i;
			}
			a[i] = -a[i];
		}
		long long sum1 = 0, ans1 = 0;
		int id1 = 0;
		for (int i = n; i > 0; --i) {
			sum1 += a[i];
			if (sum1 < 0) sum1 = 0;
			if (sum1 > ans1) {
				ans1 = sum1;
				id1 = i;
			}
		}
	//	printf("%lld %lld %lld\n", sum, ans1, sum2);
		ans = max(ans, sum2 + ans1);
 		printf("%lld\n", ans);
	}
	return 0;
}

/*
5 3
500 Margherita
600 Salami
700 Hawai
800 Speciale
900 Doener
*/

F:点击打开链接

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <vector>
using namespace std;

typedef long long ll;
const int N = 105;

template <class T>
inline bool rd(T &ret) {
	char c; int sgn;
	if(c=getchar(),c==EOF) return 0;
	while(c!='-'&&(c<'0'||c>'9')) c=getchar();
	sgn=(c=='-')?-1:1;
	ret=(c=='-')?0:(c-'0');
	while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
	ret*=sgn;
	return 1;
}
template <class T>
inline void pt(T x) {
    if (x <0) {
        putchar('-');
        x = -x;
    }
    if(x>9) pt(x/10);
    putchar(x%10+'0');
}

int main() {
	int T, n;
	ll a, b;
	scanf("%d", &T);
	while(T-- > 0) {
		scanf("%d%lld%lld", &n, &a, &b);
		if(a < b) swap(a, b);

		int cnt = 0;
		while(b % 2 != 1) {
			b /= 2;
			cnt ++;
		}

		printf("%d\n", n-cnt);
	}

	return 0;
}

G:点击打开链接

题意:

给定[0,n] * [0,m]的二维矩阵

矩阵内有k个绿点

下面k行给出绿点坐标,(保证给出的坐标都不是整数且 0 <= x <= n , 0 <= y <= m

问:

用宽度为1的刷子,一次可以把一行染色或者把一列染色

问最少要使用几次刷子

思路:

二分匹配,把所有点都映射到该点所在的方格的左下角坐标里(即舍弃小数部分)

然后就是一道经典的行列匹配,和排兵布阵一样做法。

代码:点击打开链接

H:点击打开链接

题意:

第一行给出C, n, Q

开始有一个编号[0, C) 的全0序列。

下面Q行操作

status id (询问下标为id的值)

groupchange [l, r] val  把区间[l,r] 每次+1(或-1)val次,当区间中某一个点达到0或n时则操作停止,输出实际+1(或-1)的值

change id val 同上,只是单点操作。

思路:

裸线段树,维护区间最值和加个lazy标记就可以了

代码:点击打开链接

J:点击打开链接

题意:

可以使用前k种字符(a-z, A-Z, 0-9),字符串s(len<1e6)

问:1、构造一个最小的串使得不为s的子序列,输出最小串的长度 2、这样的串有多少个(mod 1e9+7)

思路:

dp

f[] <- 0

dp[] <- 0

now[] <- n+1

f[n+1] <- 1

dp[n + 1] <- 1

for i from n down to 0:

for j in ∑

if dp[now[j]] + 1 < dp[i]:

dp[i] <-dp[now[j]] + 1

f[i] <- 0

if dp[i] == dp[now[j]] + 1:

f[i] <- f[i] +f[now[j]]

now[s[i]] <- i

第一问答案为dp[0]-1

f[0]就是第二问答案

第二个for可以用维护最大次大代替?

K:点击打开链接

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>

using namespace std;

const int MAX_N = 100007;

int n, p;
int a[MAX_N];
char s[107];

int main() {
	while(~scanf("%d%d", &n, &p)) {
		for (int i = 0; i < n; ++i) {
			scanf("%d%s", &a[i], s);
		}
		int l = n / 3, r = n + 1 - n / 3 - (n % 3 > 1);
		if (l < p && p < r) puts("YES");
		else puts("NO");
	}
	return 0;
}

/*
5 3
500 Margherita
600 Salami
700 Hawai
800 Speciale
900 Doener
*/
时间: 2024-08-05 02:26:15

湖南多校对抗赛(2015.03.15)9题题解 ABCEFGHJK的相关文章

湖南多校对抗赛3.28 J - Jerry&#39;s trouble

Problem J: Jerry's trouble Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 96  Solved: 46 [Submit][Status][Web Board] Description Jerry is caught by Tom. He was penned up in one room with a door, which only can be opened by its code. The code is the

湖南多校对抗赛(2015.03.28) E Longest Increasing Subsequence Again

题意:给你一个序列,问你删除掉连续的一段,使得剩下的序列的最长上升字串最大,问你这个最大值. 解题思路:分段dp,  dp[i][0] ,dp[i][1]   , 0表示前面没有切过,只能从前一个数的0状态得到,1状态表示前面已经切过了,能从前一个的1状态得到,也能从 在他前面的比他值小的dp[j][0](j < i && a[j] < a[i])的最大值得到,这里用线段树维护就行了. 解题代码: 1 // File Name: b.cpp 2 // Author: darkd

湖南多校对抗赛(2015.03.28) G Good subsequence

题意:找到一个序列中极值<=k的最长字串的长度. 解题思路:set容器双递推. 解题代码: 1 // File Name: g.cpp 2 // Author: darkdream 3 // Created Time: 2015年03月28日 星期六 12时04分39秒 4 5 #include<vector> 6 #include<list> 7 #include<map> 8 #include<set> 9 #include<deque>

湖南多校对抗赛(2015.03.28) A Rectangle

题意:给你一些最多宽为2 的木板,让你放在一个宽为二的盒子里面,问你这个盒子最短有多长. 解题思路:DP,离中间最近的那个值. 解题代码: 1 // File Name: a.cpp 2 // Author: darkdream 3 // Created Time: 2015年03月28日 星期六 12时13分56秒 4 5 #include<vector> 6 #include<list> 7 #include<map> 8 #include<set> 9

湖南多校对抗赛(2015.03.28) B Design road

题意:给你起点(0,0),终点(x,y),中间有很多条河, 在河上面建桥花费c1,在陆地建路花费c2,问你最小花费是多少. 解题思路:我们知道,我们考虑的时候完全可以把河都移动到一边来求,这样只需要三分就行了. 解题代码: 1 // File Name: b.cpp 2 // Author: darkdream 3 // Created Time: 2015年03月28日 星期六 13时26分39秒 4 5 #include<vector> 6 #include<list> 7 #

湖南多校对抗赛(2015.03.28) H SG Value

题意:给你一个集合,动态插入 ,动态询问,然后问你这个集合的sg值(这个集合用加法运算不能产生的那个最小正整数)是多少. 解题思路:假设我们现在的这个SG值是 x 1)现在插入集合里面一个数v   如果这个v > x ,那么显然  sg值x不变,  把v放进从小到大的优先队列中 2)如果这个 v <= x 那么sg值x肯定就会变成  x + v, 每更新一次 sg值,就去看优先队列top元素是否是 小于等于 x的 ,如果小于等于,其实就等于把这个top元素进行1操作,这样就不会错了. 解题代码

湖南多校对抗赛(2015.03.28) I Inversion Sequence

题意:给你一个序列a[i],代表 i这个数 在b数列中有多少个值在它前面且比它大,问你求B序列 解题思路:线段树的简单应用,找第几个空,类似二分. 解题代码: 1 // File Name: i.cpp 2 // Author: darkdream 3 // Created Time: 2015年03月28日 星期六 12时56分11秒 4 5 #include<vector> 6 #include<list> 7 #include<map> 8 #include<

湖南多校对抗赛(2015.03.28)CSU1547~1536 题解

比赛链接:点击打开链接 A:点击打开链接 题意: 有2种矩阵1*x和2*x, 用最小的矩阵2*m来把这些框住,使得m最小,输出最小的m 输入: n个矩阵 下面n行给出wi, xi, wi的取值只有1,2两种,且矩阵不能旋转重叠. 思路: 矩阵宽为2就直接加到答案上,所以只考虑矩阵宽为1. dp[i]表示第一行能放的宽度,类似背包求出这个dp 然后if(dp[i] is ok) ans = min(ans, max(sum-i, i) ); #include <iostream> #includ

湖南多校对抗赛(2015.05.03)Problem B: War

并查集.从后往前加边. #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> using namespace std; const int maxn = 1000000 + 10; int father[maxn], u[maxn], v[maxn], Q, q[maxn], ans[maxn], ff[maxn]; int find(int x) { if (x