【杂记】之1024程序员节社团模拟赛题目与题解

T1 aab

问题陈述

在长度为 A + B A + B A+B 的字符串中,包含 A A A 次出现的 "a "和 B B B 次出现的 “b”,请找出按词典序排列为 K K K 的字符串。

限制因素
  • 1 ≤ A , B ≤ 30 1 \leq A, B \leq 30 1A,B30
  • 1 ≤ K ≤ S 1 \leq K \leq S 1KS ,其中 S S S 是长度为 A + B A + B A+B 的字符串的个数,包含 A A A 个出现过的 a B B B 个出现过的 b
  • 所有输入值均为整数。
输入

输入内容由标准输入法提供,格式如下:

A B K
输出

输出单个答案

输入样本 1
2 2 4

样本输出 1

baab

以下是按词典顺序排列的包含两个 "a "和两个 "b "的字符串:aabbabababbabaabbababbaa。第四个字符串 baab 被输出出来。

输入样本 2
30 30 118264581564861424

输出示例 2

bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

K K K 可能不适合 32 32 32 位整数类型。

T2 sums

问题陈述

给定的是一棵有 N N N 个顶点的树。顶点的编号为 1 , 2 , … , N 1,2,\ldots ,N 1,2,,N ,连接顶点 u i u_i ui v i v_i vi i i i -th 边是一条无向边。

求每个整数 i , ( 1 ≤ i ≤ N ) i,(1 \leq i \leq N) i,(1iN) 中的 ∑ j = 1 1 d i s ( i , j ) \sum ^1 _{j=1}dis(i,j) j=11dis(i,j)

这里, d i s ( i , j ) dis(i,j) dis(i,j) 表示从顶点 i i i 到顶点 j j j 所要经过的最小边数。

限制因素
  • 2 ≤ N ≤ 2 × 1 0 5 2 \leq N \leq 2 \times 10^5 2N2×105
  • 1 ≤ u i , v i ≤ N 1 \leq u_i , v_i \leq N 1ui,viN
  • 给定图形是一棵树。
  • 输入值均为整数。
输入

输入内容由标准输入法提供,格式如下:

N
u1 v1
u2 v2
...
u{N-1} v{N-1}
输出

输出 N N N 行。

i i i -th 行应包含 ∑ j = 1 N d i s ( i , j ) \sum_{j=1}^{N}dis(i,j) j=1Ndis(i,j)

输入样本 1
3
1 2
2 3

样本输出 1

3
2
3

我们有

d i s ( 1 , 1 ) + d i s ( 1 , 2 ) + d i s ( 1 , 3 ) = 0 + 1 + 2 = 3 dis(1,1)+dis(1,2)+dis(1,3)=0+1+2=3 dis(1,1)+dis(1,2)+dis(1,3)=0+1+2=3 ,

d i s ( 2 , 1 ) + d i s ( 2 , 2 ) + d i s ( 2 , 3 ) = 1 + 0 + 1 = 2 dis(2,1)+dis(2,2)+dis(2,3)=1+0+1=2 dis(2,1)+dis(2,2)+dis(2,3)=1+0+1=2 ,

d i s ( 3 , 1 ) + d i s ( 3 , 2 ) + d i s ( 3 , 3 ) = 2 + 1 + 0 = 3 dis(3,1)+dis(3,2)+dis(3,3)=2+1+0=3 dis(3,1)+dis(3,2)+dis(3,3)=2+1+0=3 .

输入样本 2
2
1 2

输出示例 2

1
1

T3 dice

问题陈述

投掷一个有六个面的骰子点数分别为 1 , 2 , … , 6 1,2,\ldots,6 1,2,,6 ,当投掷 A A A 次时,点数之和可能为 B B B 吗?

限制因素
  • 1 ≤ A ≤ 100 1 \leq A \leq 100 1A100
  • 1 ≤ B ≤ 1000 1 \leq B \leq 1000 1B1000
  • A A A B B B 都是整数。
输出

如果可以得到 B B B 的总和,则打印 Yse;否则,打印 No

输入样本 1
2 11

样本输出 1

Yse

扔两次 6 6 6 面的骰子,有两种方法得到 11 11 11 的和:

  • 第一次掷出 6 6 6 ,第二次掷出 5 5 5
  • 第一次掷得 5 5 5 ,第二次掷得 6 6 6
输入样本 2
2 13

输出示例 2

No

扔两次 6 6 6 (面)骰子是不可能得到 13 13 13 的和的。

输入样本 3
100 600

输出示例 3

Yse

T4 mex

问题陈述

让我们定义 m e x ( x 1 , x 2 , x 3 , … , x k ) \mathrm{mex}(x_1, x_2, x_3, \dots, x_k) mex(x1,x2,x3,,xk) 为不出现在 x 1 , x 2 , x 3 , … , x k x_1, x_2, x_3, \dots, x_k x1,x2,x3,,xk 中的最小非负整数。

现在给你一个长度为 N N N 的整数序列 A 1 , A 2 , A 3 , … , A N A_1, A_2, A_3, \dots, A_N A1,A2,A3,,AN 和一个区间长度 M M M ,在该序列中任取一个长度为 M M M 的子串,求这个字串的 m e x mex mex 值。

即计算对于 0 ≤ i ≤ N − M 0 \le i \le N - M 0iNM 的每个整数 i i i ,我们计算 m e x ( A i + 1 , A i + 2 , A i + 3 , … , A i + M ) \mathrm{mex}(A_{i + 1}, A_{i + 2}, A_{i + 3}, \dots, A_{i + M}) mex(Ai+1,Ai+2,Ai+3,,Ai+M)

请计算结果中的最小值。

限制因素
  • 1 ≤ M ≤ N ≤ 1.5 × 1 0 6 1 \le M \le N \le 1.5 \times 10^6 1MN1.5×106
  • 0 ≤ A i < N 0 \le A_i \lt N 0Ai<N
  • 所有输入值均为整数。
输入

输入内容由标准输入法提供,格式如下:

N M
A1 A2 A3 ... AN
输出

输出唯一答案

输入样本 1
3 2
0 0 1

样本输出 1

1

我们有

  • i = 0 i = 0 i=0 m e x ( A i + 1 , A i + 2 ) = m e x ( 0 , 0 ) = 1 \mathrm{mex}(A_{i + 1}, A_{i + 2}) = \mathrm{mex}(0, 0) = 1 mex(Ai+1,Ai+2)=mex(0,0)=1
  • i = 1 i = 1 i=1 m e x ( A i + 1 , A i + 2 ) = m e x ( 0 , 1 ) = 2 \mathrm{mex}(A_{i + 1}, A_{i + 2}) = \mathrm{mex}(0, 1) = 2 mex(Ai+1,Ai+2)=mex(0,1)=2

因此,答案是 1 1 1 2 2 2 中的最小值,即 1 1 1

输入样本 2
3 2
1 1 1

输出示例 2

0

我们有

  • i = 0 i = 0 i=0 m e x ( A i + 1 , A i + 2 ) = m e x ( 1 , 1 ) = 0 \mathrm{mex}(A_{i + 1}, A_{i + 2}) = \mathrm{mex}(1, 1) = 0 mex(Ai+1,Ai+2)=mex(1,1)=0
  • i = 1 i = 1 i=1 m e x ( A i + 1 , A i + 2 ) = m e x ( 1 , 1 ) = 0 \mathrm{mex}(A_{i + 1}, A_{i + 2}) = \mathrm{mex}(1, 1) = 0 mex(Ai+1,Ai+2)=mex(1,1)=0
输入样本 3
3 2
0 1 0

输出示例 3

2

我们有

  • i = 0 i = 0 i=0 时: m e x ( A i + 1 , A i + 2 ) = m e x ( 0 , 1 ) = 2 \mathrm{mex}(A_{i + 1}, A_{i + 2}) = \mathrm{mex}(0, 1) = 2 mex(Ai+1,Ai+2)=mex(0,1)=2
  • i = 1 i = 1 i=1 时: m e x ( A i + 1 , A i + 2 ) = m e x ( 1 , 0 ) = 2 \mathrm{mex}(A_{i + 1}, A_{i + 2}) = \mathrm{mex}(1, 0) = 2 mex(Ai+1,Ai+2)=mex(1,0)=2
输入样本 4
7 3
0 0 1 2 0 1 0

样本输出 4

2

T5 xor

问题描述

给定 n n n 个整数(数字可能重复),求在这些数中选取任意个,使得他们的异或和最大。

输入格式

第一行一个数 n n n,表示元素个数

接下来一行 n n n 个数

输出格式

仅一行,表示答案。

样例输入1

2
1 1

样例输出1

1

样例输入2

4
1 5 9 4

样例输出2

13

提示

$ 1 \leq n \leq 50, 0 \leq S_i < 2 ^ {50} $

T6 hello

题目描述

编写一个能够输出 HELL0 HTU! 的程序。

注意:使用英文标点符号!

样例输入 1

样例输出 1

HELL0 HTU!

T7 snake

题目描述

按照要求输出下列图形

给定一个整数 n n n,输出一个 n ∗ n n * n nn 的数字正方形。

具体格式请看样例。

输入格式

输入一个正整数 n ( 1 ≤ n ≤ 500 ) n (1 \leq n \leq 500) n(1n500)

输出格式

n ∗ n n * n nn 的蛇形矩阵

样例输入1

3

样例输出1

1 2 3
8 9 4
7 6 5

样例输入2

4

样例输出2

1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7

题解:

T1

#include<bits/stdc++.h>
using namespace std;
#define int long long
int a,b,k;
int gcd(int x,int y)
{
    if(y == 0) return x ;
    else return gcd(y , x % y);
}
void dfs(int n , int m , int x)
{
	if(n == 0)
	{
		while(m --) cout << 'b';
		return ;
	}
	if(m == 0)
	{
		while(n --) cout << 'a';
		return ;
	}
	int q = 1 , w , ci = n + m - 1 , hh = 1 , yue = max(n - 1 , m) , shao = min(m , n - 1);
	for(int i = yue + 1 , j = 1 ; i <= ci ; i ++ , j++)
	{
		if(j <= shao) hh *= j;
		q *= i ;
		w = gcd(q , hh);
		q /= w ; hh /= w ;
	}
	if(q < x){cout << 'b'; dfs(n , m - 1 , x - q);}
	else {cout << 'a' ; dfs(n - 1 , m , x);}
}
signed main()
{
	scanf("%lld%lld%lld" ,&a ,&b ,&k);
	dfs(a , b , k);
	return 0;
}

考虑 b b b 在前时字典序更大,一位一位输出,默认该位为 a a a ,计算这种情况下后面还有几种可能,即最大字典序是否能达到要求的 k k k ,若合理则为 a a a ,否则为 b b b

代码丑陋,但基本是组合的思想,感觉不用太看代码推下公式即可。

T2

#include<bits/stdc++.h>
using namespace std;
#define N 1000010
#define int long long
struct eo
{
	int y , nxt , v;
}e[N];
int hd[N] , num[N] , n , tot , ans[N] , sum , fav[N];
void lian(int x,int y,int v)
{
	e[++ tot].nxt = hd[x] ; hd[x] = tot ; e[tot].y = y ; e[tot].v = v;
}
void dfs(int x,int fa,int sg)
{
    num[x] = 1 ; sum += sg;
    for(int i = hd[x] ; i ; i = e[i].nxt)
	{
	    int y = e[i].y ;
	    if(y == fa) continue;
		dfs(y , x , sg + e[i].v);
	    fav[y] = e[i].v ; num[x] += num[y] ;
	}
}
void dfs2(int x,int fa)
{
    for(int i = hd[x] ; i ; i = e[i].nxt)
	{
	    int y = e[i].y;
	    if(y == fa) continue;
	    ans[y] = ans[x] + n * e[i].v - num[y] * e[i].v * 2;
	    dfs2(y , x);
	}
}
signed main()
{
    scanf("%lld" ,&n) ; int x , y ;
    for(int i = 1 ; i < n ; i ++)
	{
		scanf("%lld%lld" ,&x ,&y) ;
		lian(x , y , 1) ; lian(y , x , 1) ;
	}
	dfs(1 , 0 , 0) ;
	ans[1] = sum ;
	dfs2(1 , 0);
	for(int i = 1 ; i <= n ; i ++)
		printf("%lld\n" ,ans[i]);
	return 0;
}

换根DP模板题。

T3

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n,m;
	scanf("%d%d" ,&n ,&m);
	if(n * 6 >= m && n <= m) printf("Yse");
	else printf("No");
	return 0 ;
}

考虑一个骰子点数从 1 1 1 6 6 6 ,投掷 n n n 个点数和在 n n n 6 n 6n 6n 之间为合法,注意不是输出 Y e s Yes Yes 而是输出 Y s e Yse Yse

T4

#include <bits/stdc++.h>
using namespace std;
#define N 2000010
int num[N] , a[N] , n , k , ans = 9999999;
bool flag;
void work()
{
	int head = k , tail = 1;
	for(int i = tail ; i <= head ; i ++) num[a[i]]++;
	for(int i = 0 ; ; i ++)
	{	
		if(num[i] == 0)
		{
			ans = min(ans , i) ;
			if(ans == 0)
			{
				cout << 0 ;
				flag = 1 ;
				return ;
			}
			break ;
		}
	}	
	while(head < n)
	{
		head ++ ;
		num[a[head]] ++ ;
		num[a[tail]] -- ;
		if(num[a[tail]] == 0) ans = min(ans , a[tail]);
		tail ++;
	}
}
int main()
{
	scanf("%d%d" ,&n ,&k);
	for(int i = 1 ; i <= n ; i ++)
		scanf("%d",&a[i]) ;
	work() ;
	if(flag == 0) cout << ans ;
	return 0;
}

可以用线段树或树状数组等高级数据结构,也可以用这么一个桶水过去,把第一个区间内的所有数记录入桶中,动态向右平移的过程中,每向右平移一位就把尾部的数对应的桶数据减一,新加入头部的加一。时间复杂度 O ( N ) O(N) O(N)

举例树状数组代码:

#include<bits/stdc++.h>
#define N 1600006
#define LL long long 
#define LB long double
using namespace std;

int n,m;
int ans = 1e8 , a[N] , sp = 0 ;
int mp[N] , tr[N];

inline int qr()
{
	char a=0;int w=1,x=0;
	while(a<'0'||a>'9'){if(a=='-')w=-1;a=getchar();}
	while(a<='9'&&a>='0'){x=(x<<3)+(x<<1)+(a^48);a=getchar();}
	return x*w;
}

const int K = 1500002;

inline void add(int x,int k)
{
	for(int i = x ; i <= K ; i += i & -i) tr[i] += k ;
}

inline int que(int x)
{
	int res = 0 ;
	for(int i = x ; i ; i -= i & -i) res += tr[i];
	return res ;
}

int jac[123];
inline int ask()
{
	int pos = 1 ;
	for(int i = 21 ; i >= 0 ; i --)
		if(pos + jac[i] - 1 <= K)
		{
			int op = que(pos + jac[i] - 1);
			if(op == pos+jac[i] - 1)
				pos += jac[i];
		}
	return pos;
}

int main()
{
	n = qr();
	m = qr();
	jac[0] = 1;
	for(int i = 1 ; i <= 21 ; i ++) jac[i] = jac[i - 1] << 1;
	for(int i = 1 ; i <= n ; i ++) a[i] = qr() + 1;
	for(int i = 1 ; i <= n ; i ++)
	{
		mp[a[i]] ++;
		if(mp[a[i]] == 1) add(a[i] , 1);
		if(i>=m)
		{
			ans = min(ans,ask());
			mp[a[i - m + 1]] --;
			if(!mp[a[i - m + 1]]) add(a[i - m + 1] , -1);
		}
	}
	printf("%d\n",ans - 1);
	return 0;
}

T5

#include<bits/stdc++.h>
using namespace std;
#define N 60
int n ;
long long a[N] ,ans;
int main()
{
	scanf("%d" , &n);
	for(int i = 1; i <= n; i ++)
		scanf("%lld" , &a[i]);
	for(int i = 1 ; i <= n ; i++)
	{
		for(int j = i + 1 ; j <= n ; j++)
			if(a[j] > a[i]) swap(a[j] , a[i]);
		if(a[i] == 0) break;
		for(int j = 50 ; j >= 0 ; j --)
			if(a[i] >> j & 1)
			{
				for(int c = 1 ; c <= n ; c ++)
					if(i != c && (a[c] >> j & 1)) a[c] ^= a[i];
				break;
			}
	}
	for(int i = 1;i <= n ;i ++) ans ^= a[i];
	printf("%lld",ans);
	return 0;
}

线性基模板题。

T6

#include<bits/stdc++.h>
using namespace std;
int main()
{
	printf("HELL0 HTU!") ;
	return 0 ;
}

养成复制关键字符串的习惯。

T7

#include<bits/stdc++.h>
using namespace std;
int x , y , n , zs , ys , zx , yx , f , h , a[800][800] ; 
int main()
{
	cin >> n;
	ys = n; yx = 2 * n - 1; zx = 3 * n - 2; zs = 1;
	int nu1 = 1 , nu2 = 1 , nu3 = 1 , nu4 = 1 ;
	int num = (n + 1) / 2 ;
	x = 1 ; y = 1 ; h = n + 2 ; f = 1 ;
	for(int i = 1 ; i <= n * n; i ++)
	{
		if(i == zs) h = h - 2;
		a[x][y] = i ;
		if(i == zx)
		{
			f = 4 ;
			if(nu1<num) zx += 4 * h - 10 ;
			nu1++;
		}
		else if(i == yx)
		{
			f = 3 ;
			if(nu2<num) yx += 4 * h - 8 ;
			nu2++;
		}
		else if(i == ys)
		{
			f = 2 ;
			if(nu3<num) ys += 4 * h - 6 ;
			nu3++;
		}
		else if(i == zs)
		{
			f = 1 ;
			
			if(nu4 < num && nu4 == 1) zs += 4 * h - 5 ;
			else if(nu4 < num) zs += 4 * h - 4;
			nu4++;
		} 
		if(f == 1) y ++;
		if(f == 2) x ++;
		if(f == 3) y --;
		if(f == 4) x --;
	}
	for(int i = 1 ; i <= n ; i ++)
	{
		for(int j = 1 ; j <= n ; j ++)
		{
			cout << a[i][j] << ' ';
		}
		cout << endl;
	}
	return 0 ;
}

模拟,方法很多种,这里是模拟从 1 1 1 n 2 n^2 n2 环形向内的过程给二维数组挨个赋值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值