Educational Codeforces Round 89

A. Shovels and Swords

Polycarp plays a well-known computer game (we won't mention its name). In this game, he can craft tools of two types — shovels and swords. To craft a shovel, Polycarp spends two sticks and one diamond; to craft a sword, Polycarp spends two diamonds and one stick.

Each tool can be sold for exactly one emerald. How many emeralds can Polycarp earn, if he has a sticks and b diamonds?

Input
The first line contains one integer t (1≤t≤1000) — the number of test cases.

The only line of each test case contains two integers a and b (0≤a,b≤109) — the number of sticks and the number of diamonds, respectively.

Output
For each test case print one integer — the maximum number of emeralds Polycarp can earn.

Example

input

4
4 4
1000000000 0
7 15
8 7

output

2
0
7
5

Note

In the first test case Polycarp can earn two emeralds as follows: craft one sword and one shovel.

In the second test case Polycarp does not have any diamonds, so he cannot craft anything.

题意:游戏我的世界中做一把铲子2木棍1钻石,一把剑2钻石1木棍,每件工具可以卖一个绿宝石,给a根木棍b个钻石,最多能卖多少绿宝石。

假设做x把铲子,y把剑,2x+y<=a,x+2y<=b,求x+y最大

分情况求解

#include 
#define LL long long
#define ULL unsigned long long
#define Pi acos(-1.0)
#define INF 2147483647
#define eps 1e-9
#define MS 200009
#define mod 998244353
using namespace std;
// Notice the data size

int n,m,k,ans;
int p[MS];

int main() {
	cin >> k;
	while(k--){
		cin >> n >> m;
		if(2*n<=m) printf("%d\n",n); // 钻石过多
		else if(2*m<=n) printf("%d\n",m); // 棒子过多
		else printf("%d\n",(n+m)/3); // (x+y)*3<=a+b
	}
	
	return 0;
}

三分

#include 
#define LL long long
#define Pi acos(-1.0)
#define INF 2147483646
#define eps 1e-9
#define MS 100009
using namespace std;
// Notice the data size

int n,m,k,ans;
int p[MS];

int check(int x) { // 计算能卖多少绿宝石
	int lv_n = n - 2*x;
	int lv_m = m - x;
	x += min(lv_n,lv_m/2);
	ans = max(x,ans); // 更新ans
	return x;
}

int main() {
	cin >> k;
	while(k--) {
		int l,r,m1,m2;
		cin >> n >> m;
		l = 0 ,r = min(n/2,m);
		ans = max(check(l),check(r)); // 求两端
		while(l+1check(m2)) {
				r = m2;
			} else l = m1;
		}
		cout << ans << endl;
	}
}

B. Shuffle

You are given an array consisting of n integers a1, a2, ..., an. Initially ax=1, all other elements are equal to 0.

You have to perform m operations. During the i-th operation, you choose two indices c and d such that li≤c,d≤ri, and swap ac and ad.

Calculate the number of indices k such that it is possible to choose the operations so that ak=1 in the end.

Input
The first line contains a single integer t (1≤t≤100) — the number of test cases. Then the description of t testcases follow.

The first line of each test case contains three integers n, x and m (1≤n≤109; 1≤m≤100; 1≤x≤n).

Each of next m lines contains the descriptions of the operations; the i-th line contains two integers li and ri (1≤li≤ri≤n).

Output
For each test case print one integer — the number of indices k such that it is possible to choose the operations so that ak=1 in the end.

Example

input

3
6 4 3
1 6
2 3
5 5
4 1 2
2 4
1 2
3 3 2
2 3
1 2

outputCopy

6
2
3

Note
In the first test case, it is possible to achieve ak=1 for every k. To do so, you may use the following operations:

swap ak and a4;
swap a2 and a2;
swap a5 and a5.

In the second test case, only k=1 and k=2 are possible answers. To achieve a1=1, you have to swap a1 and a1 during the second operation. To achieve a2=1, you have to swap a1 and a2 during the second operation.

题意:给出了一个由n个整数a1,a2,…,an组成的数组。最初ax=1,所有其他元素都等于0.

你必须执行m操作。在第i个操作中,选择两个索引c和d,使li≤c,d≤ri,并交换ac和ad.

计算索引k的数量,以便可以选择操作,以便ak最终为1。

例如:
在第一个测试用例中,每k可以实现ak=1。为此,可以使用以下操作:

交换ak和a4;
交换a2和a2;
交换a5和a5。

在第二个测试用例中,只有k=1和k=2是可能的答案。
要达到a1=1,您必须在第二次操作期间交换a1和a1。要实现a2=1,必须在第二次操作期间交换a1和a2。

解:向左向右拓展能够得到的区间

#include 
#define LL long long
#define Pi acos(-1.0)
#define INF 2147483646
#define eps 1e-9
#define MS 100009
using namespace std;
// Notice the data size
 
int n,m,k;
int p[MS];
 
int main() {
	cin >> k;
	while(k--){
		int l,r;
		int op;
		cin >> n >> m >> op;
		l = r = m; // 无任何操作的情况下,只有 ak 能为 1
		for(int i=0;i> a >> b;
			if(a<=l&&r<=b){ // 向左向右扩展
				l = a;
				r = b;
			}
			else if(l<=b&&b<=r&&ar){ //向右扩展
				r = b;
			}
		}
		printf("%d\n",r-l+1);
	}
	
}

C. Palindromic Paths

You are given a matrix with n rows (numbered from 1 to n) and m columns (numbered from 1 to m). A number ai,j is written in the cell belonging to the i-th row and the j-th column, each number is either 0 or 1.

A chip is initially in the cell (1,1), and it will be moved to the cell (n,m). During each move, it either moves to the next cell in the current row, or in the current column (if the current cell is (x,y), then after the move it can be either (x+1,y) or (x,y+1)). The chip cannot leave the matrix.

Consider each path of the chip from (1,1) to (n,m). A path is called palindromic if the number in the first cell is equal to the number in the last cell, the number in the second cell is equal to the number in the second-to-last cell, and so on.

Your goal is to change the values in the minimum number of cells so that every path is palindromic.

Input
The first line contains one integer t (1≤t≤200) — the number of test cases.

The first line of each test case contains two integers n and m (2≤n,m≤30) — the dimensions of the matrix.

Then n lines follow, the i-th line contains m integers ai,1, ai,2, ..., ai,m (0≤ai,j≤1).

Output
For each test case, print one integer — the minimum number of cells you have to change so that every path in the matrix is palindromic.

Example

input

4
2 2
1 1
0 1
2 3
1 1 0
1 0 0
3 7
1 0 1 1 1 1 1
0 0 0 0 0 0 0
1 1 1 1 1 0 1
3 5
1 0 1 0 0
1 1 1 1 0
0 0 1 0 0

outputCopy

0
3
4
4

Note
The resulting matrices in the first three test cases:
Educational Codeforces Round 89_第1张图片

题意:从(1,1)到(n,m)的每条路径要变成回文,最少修改 n,m 矩阵中的几个数字。

解:从开头走 x 步和从结尾走 x 步对应的值要相等

#include 
#define LL long long
#define Pi acos(-1.0)
#define INF 2147483646
#define eps 1e-9
#define MS 109
using namespace std;
// Notice the data size
 
int n,m,k;
int p[MS][MS];
 
int main() {
	cin >> k;
	while(k--){
		int cnt = 0;
		cin >> n >> m;
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				cin >> p[i][j];
			}
		}
		int h = (n+m)/2;
		for(int j=1;j<=h;j++){
			int t0,t1; // 计 0 ,1 数量
			t0 = t1 = 0;
			for(int i=(j<=m?1:(j-m+1));i<=(j<=n?j:n);i++){
				if(p[i][j-i+1]==1) t1++; // 左上角
				else t0++;
				if(p[n-i+1][m-j+i]==1) t1++; // 右下角
				else t0++;
			}
			if((n+m)%2==0&&j==h) break;
			cnt += min(t0,t1); // 取 0 ,1 中数量小的一个
		}
		printf("%d\n",cnt);
	}
	return 0;
}

D. Two Divisors

You are given n integers a1,a2,…,an.

For each ai find its two divisors d1>1 and d2>1 such that gcd(d1+d2,ai)=1 (where gcd(a,b) is the greatest common divisor of a and b) or say that there is no such pair.

Input
The first line contains single integer n (1≤n≤5⋅105) — the size of the array a.

The second line contains n integers a1,a2,…,an (2≤ai≤107) — the array a.

Output
To speed up the output, print two lines with n integers in each line.

The i-th integers in the first and second lines should be corresponding divisors d1>1 and d2>1 such that gcd(d1+d2,ai)=1 or −1 and −1 if there is no such pair. If there are multiple answers, print any of them.

Example

input

10
2 3 4 5 6 7 8 9 10 24

output

-1 -1 -1 -1 3 -1 -1 -1 2 2
-1 -1 -1 -1 2 -1 -1 -1 5 3

Note
Let's look at a7=8. It has 3 divisors greater than 1: 2, 4, 8. As you can see, the sum of any pair of divisors is divisible by 2 as well as a7.

There are other valid pairs of d1 and d2 for a10=24, like (3,4) or (8,3). You can print any of them.

题意:给你n个整数a1,a2,…,an。

对于每个ai,找到其两个除数d1>1和d2>1,使得gcd(d1+d2,ai)=1(其中gcd(a,b)是a和b的最大公约数),或者说不存在这样的对。

解:找 ai 的两个最小的两个不同质因数,找不到则 -1,-1 . 用到欧拉筛法 1s 以内,普通筛法 1s 多一点 .

#include 
#include 
#define LL long long
#define Pi acos(-1.0)
#define INF 2147483646
#define eps 1e-9
#define MS 51
using namespace std;
// Notice the data size

int n,m,f = 1,num;
const int ms=1e6+1,maxn=1e7+1;
int a[ms],ans[ms][2];
int prime[maxn];      // 就是个素数表, prime[] = {0,2,3,5,7...};
bool sf[maxn]; // 判断这个数是不是素数, sf[2] = true;

void sushu() { // 欧拉筛
	// num 用来记筛到第几个质数
	memset(sf,true,sizeof(sf));
	for(int i=2; i<=maxn; i++) {    
		if(sf[i]) prime[++num]=i;     
		for(int j=1; j<=num; j++) {    
			if(i*prime[j]>maxn) break; 
			sf[i*prime[j]]=false; 
			if(i%prime[j]==0) break; 
		}
	}
	sf[1]=false;
	sf[0]=false;
}

int main() {
	sushu();
	cin >> n;
	for(int i=0; i

E. Two Arrays

You are given two arrays a1,a2,…,an and b1,b2,…,bm. Array b is sorted in ascending order (bi

You have to divide the array a into m consecutive subarrays so that, for each i from 1 to m, the minimum on the i-th subarray is equal to bi. Note that each element belongs to exactly one subarray, and they are formed in such a way: the first several elements of a compose the first subarray, the next several elements of a compose the second subarray, and so on.

For example, if a=[12,10,20,20,25,30] and b=[10,20,30] then there are two good partitions of array a:

[12,10,20],[20,25],[30];
[12,10],[20,20,25],[30].
You have to calculate the number of ways to divide the array a. Since the number can be pretty large print it modulo 998244353.

Input
The first line contains two integers n and m (1≤n,m≤2⋅105) — the length of arrays a and b respectively.

The second line contains n integers a1,a2,…,an (1≤ai≤109) — the array a.

The third line contains m integers b1,b2,…,bm (1≤bi≤109;bi

Output
In only line print one integer — the number of ways to divide the array a modulo 998244353.

Examples

input

6 3
12 10 20 20 25 30
10 20 30

output

2

input

4 2
1 3 3 7
3 7

output

0

input**

8 2
1 2 2 2 2 2 2 2
1 2

output

7

题意:给定长 n 的数组 a[] ,长 m 的数组 b[] ,将数组 a[] 划分为 m 个子区间 ,第 i 子区间的最小值与 bi 相等 ,求有多少种划分方法.

解:a[] 从后往前遍历 ,找到 bm 后标记 pos1 ,再往前遍历找到第一个小于 bm 的值标记 pos2 ,pos2 - pos1 就表示第 m 个子区间可以有几种划分方式

因为 b[] 是升序的 ,所以 a(pos1,pos2] 区间内的值 > b[m-1] . 以此类推 bm-1,bm-2 ... 各有多少种划分 ,最后相乘即是答案

#include 
#define LL long long
#define ULL unsigned long long
#define Pi acos(-1.0)
#define INF 2147483647
#define eps 1e-9
#define MS 200009
#define mod 998244353
using namespace std;
// Notice the data size
 
int flag;
int n,m,k;
LL a[MS],b[MS];
LL pos[MS][2];
 
int main() {
	memset(pos,-1,sizeof pos);
	cin >> n >> m;
	for(int i=0;i=0;i--){
		fl = 0;
		for(int j=(i==m-1?n-1:pos[i+1][1]);j>=0;j--){
			if(a[j]==b[i]&&fl == 0) {
				pos[i][0] = j; // pos[i][0] 记录第一次出现 b[i] 的位置
 				fl = 1;
			}
			else if(a[j]>=b[i]) continue;
			else{
				if(pos[i][0] == -1){ // 若没有出现 b[i] 
					flag = 1;
					break;
				}
				pos[i][1] = j; // 标记第一个小于 b[i] 的值
				break;
			} 
		}
	}
	if(flag||pos[0][1]!=-1||fl == 0){
		printf("0\n");
		return 0;
	}
	LL ans = 1;
	for(int i=1;i

你可能感兴趣的:(Educational Codeforces Round 89)