Codeforces Round #797 (Div. 3)个人题解

Print a Pedestal (Codeforces logo?)

题面翻译

题目描述

给您一些个数为 n n n 的方块,请您用这些方块构造一个台座CodeForces的徽标,每个方块必须都被使用。

这个台座包含三个宽度为 1 1 1 格的颁奖台——从左向右依次为第 2 2 2 名、第 1 1 1 名和第 3 3 3 名的位置。

1 1 1 名的颁奖台必须严格高于第 2 2 2 名的颁奖台,第 2 2 2 名的颁奖台必须严格高于第 3 3 3 名的颁奖台。 此外,每个颁奖台的高度必须大于零(即每个颁奖台必须至少包含一个方块)。

如上图所示,我们用 n = 11 n = 11 n=11 个方块构造出了合法的台座:第二名的颁奖台的高度是 4 4 4,第一名高度是 5 5 5 而第三名高度是 2 2 2

在所有的可以被构建出的台座中,我们希望让第一名的颁奖台高度最低

如果有多种可能,输出任意一种即可。

输入格式

第一行一个整数 t t t ( 1 ≤ t ≤ 1 0 4 ) (1\le t\le 10^4) (1t104) 代表数据组数

下面 t t t 行,每行一个整数 n n n ( 6 ≤ n ≤ 1 0 5 ) (6\le n\le 10^5) (6n105) 代表可以使用的方块数量。注意所有 n n n 个方块必须都被使用。

保证一个数据点中所有 n n n 的和不超过 1 0 6 10^6 106

输出格式

对于每一组测试数据,您需要输出三个整数 h 2 h_2 h2 h 1 h_1 h1 h 3 h_3 h3 ,代表了每个颁奖台高度。

在所有的可以被构建出的台座中,我们希望让第一名的颁奖台高度最低。

如果有多种可能,输出任意一种即可。

说明/提示

在第一组样例中我们不能让第一名的颁奖台台高度小于 5 5 5 ,因为如果第一名的平台高度不超过 4 4 4 ,我们最多只可以使用 4 + 3 + 2 = 9 4 + 3 + 2 = 9 4+3+2=9 个方块。

当第一名的颁奖台高度是 5 5 5 的时候,注意到 11 = 4 + 5 + 2 11 = 4 + 5 + 2 11=4+5+2 , 因此答案 4 4 4 5 5 5 2 2 2 合法。

在第二组样例中只有一种合法答案: 2 2 2 3 3 3 1 1 1

样例 #1

样例输入 #1

6
11
6
10
100000
7
8

样例输出 #1

4 5 2
2 3 1
4 5 1
33334 33335 33331
2 4 1
3 4 1
  1. 要让h1最小,就让h2,h3尽可能大。设h1 = t,有3t-3=n,t = (n+3)/3 (上去整)h2 = t-1,h3 = n-2*t+1,特判h3=0的情况
void solve(){
    cin>>n;
    int t = (n+3)/3;
    int a = t-1;
    int b = n-2*t+1;
	if(!b){
		a--;
		b++;
	}
    cout<< a<<" "<<t<<" "<<b<<endl;
}
  1. 循环,贪心。h1 = h2-1,h1+h3 = n-h2,h3>=1,h1<=n-h2-1 , h1 = min(h2-1,n-h2-1) 。枚举h2 。
void solve(){
    cin>>n;
    int a,b;
    for(int i=n-3;i>=0;i--){
        a = min(i-1,(int)n-i-1);
        b = n-i-a;
        if(a<=b){
            i++;
            a = min(i-1,(int)n-i-1);
            b = n-i-a;
            cout<<a<<" "<<i<<" "<<b<<endl;
            break;
        }
    }
}	

Array Decrements

题面翻译

本题有多组测试数据。

给定两个长度为 n n n 的序列 a a a b b b

定义一次操作为将一个序列中的所有非零整数全都减少 1。
例如对于序列 [ 3 , 5 , 4 , 1 ] [3,5,4,1] [3,5,4,1],我们对其进行两次操作之后得到的结果分别是 [ 2 , 4 , 3 , 0 ] [2,4,3,0] [2,4,3,0] [ 1 , 3 , 2 , 0 ] [1,3,2,0] [1,3,2,0]

现在我们需要求出是否可以通过对序列 a a a 进行若干次操作(也可以不做)得到序列 b b b

如果可以的话就输出 YES,反之输出 NO,对大小写不做要求。

样例 #1

样例输入 #1

6
4
3 5 4 1
1 3 2 0
3
1 2 1
0 1 0
4
5 3 7 2
1 1 1 1
5
1 2 3 4 5
1 2 3 4 6
1
8
0
1
4
6

样例输出 #1

YES
YES
NO
NO
YES
NO

写的很烂,细节多的题我都写的烂。

ll n,m,k,_;
int a[N],b[N];
void solve(){
    cin>>n;
    fo(i,1,n)cin>>a[i];
    fo(i,1,n)cin>>b[i];
    fo(i,1,n){
    	if(a[i]<b[i]){
    		puts("NO");
	    	return ;
    	}
    }
    int dist = 0x3f3f3f3f;
    int dist_aero = -0x3f3f3f3f;
    bool aero = 0;
    bool eq = 1;
    fo(i,1,n){
        if(!b[i]){
        	aero = 1;
        	dist_aero = max(dist_aero,a[i]-b[i]);
        	continue;
        }
        if(dist == 0x3f3f3f3f){
            dist = a[i]-b[i];
        }
        if(dist != a[i]-b[i]){
			eq = 0;
        }
    }
    bool ans;
    if(aero){
    	if(dist_aero>dist){
    		ans = 0;
    	}
    	else{
    		if(eq == 1) ans=1;
    		else ans = 0;
    	}
    }
    else{
    	if(eq == 1)ans=1;
    	else ans = 0;
    }
    cout<< (!ans ? "NO" : "YES") <<endl;
   
}
  1. 判a[i] < b[i] 的情况
  2. 如果 b [] 中有0的话,记录dist_zero 最大差值,dist_zero 要小于等于非0的dist的最大值
  3. 如果满足2,如果对于b非0的项,dist都相等,yes,否则no
  4. 没有0,只看dist是否相等即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const LL mod = 1e9 + 7;
const int N = 100005;

int a[N], b[N];
int main() {
    int _;
    scanf("%d", &_);
    while (_--) {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
        for (int i = 1; i <= n; i++) scanf("%d", &b[i]);
        int t = -1, ok = 1;
        for (int i = 1; i <= n; i++) {
            if (b[i]) {
                t = a[i] - b[i];
                if (t < 0) ok = 0;
                break;
            }
        }
        if (t != -1) {
            for (int i = 1; i <= n; i++) {
                if (b[i] == 0) {
                    if (a[i] > t) ok = 0;
                } else {
                    if (a[i] - b[i] != t) ok = 0;
                }
            }
        }
        puts(ok ? "YES" : "NO");
    }
    return 0;
}

Black and White Stripe

题面翻译

题意翻译

给出 n n n m m m,还有一个长度为 n n n 且只包含 BW 的字符串。

问在字符串中找出一个长度为 m m m 且只包含 B 的子串最少需要修改多少个 W

多组测试。

输入格式

The first line contains an integer $ t $ ( $ 1 \le t \le 10^4 $ ) — the number of test cases.

Next, descriptions of $ t $ test cases follow.

The first line of the input contains two integers $ n $ and $ k $ ( $ 1 \le k \le n \le 2\cdot10^5 $ ). The second line consists of the letters ‘W’ (white) and ‘B’ (black). The line length is $ n $ .

It is guaranteed that the sum of values $ n $ does not exceed $ 2\cdot10^5 $ .


给定一个01序列,求至少包含连续m个1最少需要修改多少个0。

一开始以为是dp,真的dp不出来,人都麻了 。后来看了题解,枚举m长区间,前缀和!

void solve(){
	int len = 0;
	cin>>n>>k;
	fo(i,1,n)cin>>a[i];
	fo(i,1,n){
		s[i] = s[i-1] + (a[i] == 'W');
	}
	int ans = n+1;
	for(int i=1;i<=n-k+1;i++){
		int j = i+k-1;
		ans = min(ans,s[j]-s[i-1]);
	}
	cout<<ans;
	puts("");
}

Price Maximization

题面翻译

本题有多组测试数据。

我们有 n n n 个礼物,而最终我们需要将所有的礼物两两包成 n 2 \frac{n}{2} 2n 个包裹。

每一个礼物 i i i 都有其价值 a i a_i ai,而含有礼物 i i i 与礼物 j j j 的包裹的价值是 ⌊ a i + a j k ⌋ \lfloor \frac{a_i+a_j}{k} \rfloor kai+aj

我们需要找出一个方案来使得所有包裹的价值之和最大,并求出这个最大值。

题目描述

A batch of $ n $ goods ( $ n $ — an even number) is brought to the store, $ i $ -th of which has weight $ a_i $ . Before selling the goods, they must be packed into packages. After packing, the following will be done:

  • There will be $ \frac{n}{2} $ packages, each package contains exactly two goods;
  • The weight of the package that contains goods with indices $ i $ and $ j $ ( $ 1 \le i, j \le n $ ) is $ a_i + a_j $ .

With this, the cost of a package of weight $ x $ is always $ \left \lfloor\frac{x}{k}\right\rfloor $ burles (rounded down), where $ k $ — a fixed and given value.

Pack the goods to the packages so that the revenue from their sale is maximized. In other words, make such $ \frac{n}{2} $ pairs of given goods that the sum of the values $ \left \lfloor\frac{x_i}{k} \right \rfloor $ , where $ x_i $ is the weight of the package number $ i $ ( $ 1 \le i \le \frac{n}{2} $ ), is maximal.

For example, let $ n = 6, k = 3 $ , weights of goods $ a = [3, 2, 7, 1, 4, 8] $ . Let’s pack them into the following packages.

  • In the first package we will put the third and sixth goods. Its weight will be $ a_3 + a_6 = 7 + 8 = 15 $ . The cost of the package will be $ \left \lfloor\frac{15}{3}\right\rfloor = 5 $ burles.
  • In the second package put the first and fifth goods, the weight is $ a_1 + a_5 = 3 + 4 = 7 $ . The cost of the package is $ \left \lfloor\frac{7}{3}\right\rfloor = 2 $ burles.
  • In the third package put the second and fourth goods, the weight is $ a_2 + a_4 = 2 + 1 = 3 $ . The cost of the package is $ \left \lfloor\frac{3}{3}\right\rfloor = 1 $ burle.

With this packing, the total cost of all packs would be $ 5 + 2 + 1 = 8 $ burles.

输入格式

The first line of the input contains an integer $ t $ ( $ 1 \le t \le 10^4 $ ) —the number of test cases in the test.

The descriptions of the test cases follow.

The first line of each test case contains two integers $ n $ ( $ 2 \le n \le 2\cdot10^5 $ ) and $ k $ ( $ 1 \le k \le 1000 $ ). The number $ n $ — is even.

The second line of each test case contains exactly $ n $ integers $ a_1, a_2, \dots, a_n $ ( $ 0 \le a_i \le 10^9 $ ).

It is guaranteed that the sum of $ n $ over all the test cases does not exceed $ 2\cdot10^5 $ .

输出格式

For each test case, print on a separate line a single number — the maximum possible total cost of all the packages.

样例 #1

样例输入 #1

6
6 3
3 2 7 1 4 8
4 3
2 1 5 6
4 12
0 0 0 0
2 1
1 1
6 10
2 0 0 5 9 4
6 5
5 3 8 6 3 2

样例输出 #1

8
4
0
2
1
5

提示

The first test case is analyzed in the statement.

In the second test case, you can get a total value equal to $ 4 $ if you put the first and second goods in the first package and the third and fourth goods in the second package.

In the third test case, the cost of each item is $ 0 $ , so the total cost will also be $ 0 $ .


一开始以为是背包,思路进行不下去,不会写,想到余数,还是不会。

其实就是先算一定会加上的值,凑余数。凑的方法:双指针!

void solve(){
	cin>>n>>k;
	fo(i,1,n)cin>>a[i];
	ll ans = 0;
	fo(i,1,n){
		ans += (a[i]/k);
		b[i] = a[i] % k;
	}
	
	sort(b+1,b+n+1,greater<int>());
	
	for(int i=1,j=n;i<j;i++,j--){
		while(b[i] + b[j] < k && i<j){
			j--;
		}
		if(i==j)break;
		// cout<<i<<" "<<j<<endl;
		ans++;
	}
	cout<<ans<<endl;
}

Shifting String (置换)

题面翻译

题意简述

给定一长为 n n n 的字符串 s s s(下标从 1 1 1 开始) 与 1 ∼ n 1\sim n 1n 的排列 p p p。定义 s 0 = s , s i k = s p i k − 1 s^0=s,s^k_i=s^{k-1}_{p_i} s0=s,sik=spik1。求最小的 k > 0 k>0 k>0 使 s k = s s^k=s sk=s t t t 组数据。

  • t ≤ 5000 , n ≤ 200 t\le 5000,n\le200 t5000,n200

题目描述

Polycarp found the string $ s $ and the permutation $ p $ . Their lengths turned out to be the same and equal to $ n $ .

A permutation of $ n $ elements — is an array of length $ n $ , in which every integer from $ 1 $ to $ n $ occurs exactly once. For example, $ [1, 2, 3] $ and $ [4, 3, 5, 1, 2] $ are permutations, but $ [1, 2, 4] $ , $ [4, 3, 2, 1, 2] $ and $ [0, 1, 2] $ are not.

In one operation he can multiply $ s $ by $ p $ , so he replaces $ s $ with string $ new $ , in which for any $ i $ from $ 1 $ to $ n $ it is true that $ new_i = s_{p_i} $ . For example, with $ s=wmbe $ and $ p = [3, 1, 4, 2] $ , after operation the string will turn to $ s=s_3 s_1 s_4 s_2=bwem $ .

Polycarp wondered after how many operations the string would become equal to its initial value for the first time. Since it may take too long, he asks for your help in this matter.

It can be proved that the required number of operations always exists. It can be very large, so use a 64-bit integer type.

输入格式

The first line of input contains one integer $ t $ ( $ 1 \le t \le 5000 $ ) — the number of test cases in input.

The first line of each case contains single integer $ n $ ( $ 1 \le n \le 200 $ ) — the length of string and permutation.

The second line of each case contains a string $ s $ of length $ n $ , containing lowercase Latin letters.

The third line of each case contains $ n $ integers — permutation $ p $ ( $ 1 \le p_i \le n $ ), all $ p_i $ are different.

输出格式

Output $ t $ lines, each of which contains the answer to the corresponding test case of input. As an answer output single integer — the minimum number of operations, after which the string $ s $ will become the same as it was before operations.

样例 #1

样例输入 #1

3
5
ababa
3 4 5 2 1
5
ababa
2 1 4 5 3
10
codeforces
8 6 1 7 5 2 9 3 10 4

样例输出 #1

1
6
12

提示

In the first sample operation doesn’t change the string, so it will become the same as it was after $ 1 $ operations.

In the second sample the string will change as follows:

  • $ s $ = babaa
  • $ s $ = abaab
  • $ s $ = baaba
  • $ s $ = abbaa
  • $ s $ = baaab
  • $ s $ = ababa

第一次知道这种题目的名字和通解,置换,找循环节(环)。

p[i] 各个元素连接起来,对于每个连通分量计算都存在的最小步数,所有连通分量求个lcm。

学到的内容:

lcm,ans=1开始累乘就行。gcd需要先拿一个数。


给n个各部门,每个部门有若干物品,问所有部门都有的物品编号的最大值是多少?

用map<int,int> //物品编号,出现次数,出现次数要等于部门数。这我都想不到

这题卡常,多组测试数据用scanf

char a[N];
int p[N];
bool vis[N];
// 2022年7月28日21:06:03
void solve(){
	scanf("%d%s",&n,a+1);
    fo(i,1,n)scanf("%d",&p[i]);
    vector<ll>S;
    fo(i,1,200)vis[i]=0;
    ll ans = 1;
    for(int i=1;i<=n;i++){
        if(vis[i])continue;
        vis[i]=1;
        vector<int>t;
        int next = p[i];
        t.pb(i);
        while(!vis[next]){
            t.pb(next);
            vis[next] = 1;
            next = p[next];
        }
        map<int,int>mp;// 移动次数
        for(int i=0;i<t.size();i++){
            char x = a[t[i]];
			int pos = t[i];
            int cnt=0;
            while(cnt<t.size()){
            	cnt++;
            	pos = p[pos];
            	if(a[pos] == x)mp[cnt]++;
            }
		}
 
        ll tmp;
        for(auto c:mp){
            int x = c.first;
            int y = c.second;
            if(y == t.size()){
                tmp = x;
       			ans = ans / __gcd(ans,tmp) * tmp; 
                break;
            }
       }
	
    }
    printf("%lld\n",ans);
 
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值