Gym 101532 contest (未完)

个人总结,如果有错的地方,欢迎大佬纠正。

A - Subarrays Beauty (二进制 + 贡献)

You are given an array a consisting of n integers. A subarray (l, r) from array a is defined as non-empty sequence of consecutive elements al, al + 1, ..., ar.

The beauty of a subarray (l, r) is calculated as the bitwise AND for all elements in the subarray:

Beauty(l, r) = al & al + 1 & al + 2 & ... & ar

Your task is to calculate the summation of the beauty of all subarrays (l, r) (1 ≤ l ≤ r ≤ n):

Input

The first line contains an integer T, where T is the number of test cases.

The first line of each test case contains an integer n (1 ≤ n ≤ 105), where n is the size of the array a.

The second line of each test case contains n integers a1, a2, ..., an (1 ≤ ai ≤ 106), giving the array a.

Output

For each test case, print a single line containing the summation of the beauty of all subarrays in the given array.

Example

Input

2
3
7 11 9
4
11 9 6 11

Output

40
48

Note

As input/output can reach huge size it is recommended to use fast input/output methods: for example, prefer to use scanf/printf instead of cin/cout in C++, prefer to use BufferedReader/PrintWriter instead of Scanner/System.out in Java.

A bitwise AND takes two equal-length binary representations and performs the logical AND operation on each pair of the corresponding bits, by multiplying them. Thus, if both bits in the compared position are 1, the bit in the resulting binary representation is 1 (1  ×  1 = 1); otherwise, the result is 0 (1  ×  0 = 0 and 0  ×  0 = 0). This operation exists in all modern programming languages, for example in language C++ and Java it is marked as &.

In the first test case, the answer is calculated as summation of 6 subarrays as follow:

Beauty(1, 1) + Beauty(l, 2) + Beauty(1, 3) + Beauty(2, 2) + Beauty(2, 3) + Beauty(3, 3)

(7) + (7 & 11) + (7 & 11 & 9) + (11) + (11 & 9) + (9) = 40

解题思路:求连续区间的按位与,然后把各个区间的和相加。可以先用数组把每个数的二进制储存,因为是连续区间内,如果二进制中出现是0, 那么这个二进制所在的位置的区间就可以跳过(按位与:只有两个数是1才是1)。这里是竖着储存,例如横着看是 11101,前面三位都是1,每个1都会贡献3次, 所以用公式n * (n + 1) / 2,可以参考样例给出的7, 11, 9。当然别忘了左移,如3 二进制就是11, 最左边那个1和右边那个表示的数的大小是不一样的。

AC代码:

#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;

#define ll long long

const int N = 1e5+100;
int a[21][N];

int main(){
	int t;
	scanf("%d", &t);

	while (t --) {
		memset(a,0,sizeof(a));
		int n;
		scanf("%d", &n);
		for (int i = 0; i < n; i ++) {
			int x;
			scanf("%d", &x);
			int cnt = 0;
			while (x) {
				if (x & 1) a[cnt][i] = 1;
				cnt++;
				x >>= 1;
			}
		}
		ll ans = 0;
		for (int i = 0; i < 20; i ++) {
			ll x = 0;
			for (int j = 0; j <= n; j ++) {
				if (a[i][j] == 1) x++;
				else {
					ans += (1ll << i) * (x * (x + 1) / 2);
					x = 0;
				}
			}
		}
		printf("%lld\n", ans);
	}

	return 0;
}

B -  Array Reconstructing (暴力)

You are given an array a consisting of n elements a1, a2, ..., an. Array a has a special property, which is:

ai = (ai - 1 + 1) % m, for each i (1 < i ≤ n)

You are given the array a with some lost elements from it, each lost element is replaced by -1. Your task is to find all the lost elements again, can you?

Input

The first line contains an integer T, where T is the number of test cases.

The first line of each test case contains two integers n and m (1 ≤ n ≤ 1000) (1 ≤ m ≤ 109), where n is the size of the array, and m is the described modulus in the problem statement.

The second line of each test case contains n integers a1, a2, ..., an ( - 1 ≤ ai < m), giving the array a. If the ith element is lost, then ai will be -1. Otherwise, ai will be a non-negative integer less than m.

It is guaranteed that the input is correct, and there is at least one non-lost element in the given array.

Output

For each test case, print a single line containing n integers a1, a2, ..., an, giving the array a after finding all the lost elements.

It is guaranteed that an answer exists for the given input.

Example

Input

4
5 10
1 2 3 4 5
4 10
7 -1 9 -1
6 7
5 -1 -1 1 2 3
6 10
5 -1 7 -1 9 0

Output

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

Note

As input/output can reach huge size it is recommended to use fast input/output methods: for example, prefer to use scanf/printf instead of cin/cout in C++, prefer to use BufferedReader/PrintWriter instead of Scanner/System.out in Java.

解题思路:这题被坑的有点惨,没有注意到一个数组中可能只有一个数其他都是需要填的,出现的数可能在中间。只要找到一个不是-1的数直接往前往后推就好了。

AC代码:

#include <iostream>
#include <map>
#include <cmath>
#include <string>
#include <cstring>
#include <cstdio>
using namespace std;

#define ll long long
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
const int N = 1e7;

int a[N];

int main(){
	int t;
	scanf("%d", &t);
	while (t --) {
		int n, m;
		cin >> n >> m;
		int p = 0;
		for (int i = 1; i <= n; i ++) {
			scanf("%d", &a[i]);
			if (a[i] != -1) p = i;
		}
		for (int i = 1; i <= n; i++) {
			int j = p - 1;
			while (j >= 1) {
				if (a[j] == -1) {
					if (a[j + 1] == 0) a[j] = m - 1;
					else a[j] = a[j + 1] - 1;
				}
				j--;
			}
			j = p + 1;
			while (j <= n) {
				if (a[j] == -1) {
					a[j] = a[j - 1] + 1;
					a[j] %= m;
				}
				j++;
			}
		}
		printf("%d", a[1]);
		for (int i = 2; i <= n; i++) printf(" %d", a[i]);
		printf("\n");

	}

	return 0;
}

 

c - Large Summation (暴力)

You are given an array a consisting of n element a1, a2, ..., an. For each element ai you must find another element aj (i ≠ j), such that the summation of ai and aj mod (109 + 7) (i.e. (ai + aj) % (109 + 7)) is as maximal as possible.

Can you help judges by solving this hard problem?

Input

The first line contains an integer T, where T is the number of test cases.

The first line of each test contains an integer n (2 ≤ n ≤ 105), where n is the size of the array a.

The second line of each test case contains n integers a1, a2, ..., an (0 ≤ ai < 109 + 7), giving the array a.

Output

For each test case, print a single line containing n space separated elements, such that the ith element is the answer to the ith element in the array a (i.e. the maximum value of (ai + aj) % (109 + 7)).

Example

Input

2
3
1 2 3
2
1000000000 1000000000

Output

4 5 5
999999993 999999993

Note

As input/output can reach huge size it is recommended to use fast input/output methods: for example, prefer to use scanf/printf instead of cin/cout in C++, prefer to use BufferedReader/PrintWriter instead of Scanner/System.out in Java.

解题思路:把给出的数组排好序,一边从小到大,一边从大到小遍历, 这样如果小的数加上大的数相加大于1e9+7,那么往前遍历,如果发现和前面所有小的数都大于1e9+7,那么直接加最大的数取余。因为和最大的数取余必定大于是最大的,当然还要记录原来的顺序,这种题大致都是先把暴力做法写出来再优化。

AC代码:

#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;

#define ll long long

const int N = 1e5+100;
const int p = 1e9+7;
pair<ll, int>a[N];
ll b[N];

int main(){
	int t;
	scanf("%d", &t);

	while (t --) {
		int n;
		scanf("%d", &n);
		memset(b, -1, sizeof(b));
		for (int i = 0; i < n; i ++) {
			ll x;
			scanf("%lld", &x);
			a[i] = {x, i};
		}
		sort(a, a+n);
		int j = n - 1;
		for (int i = 0; i < n; i ++) {
			for (; j >= 0; j--) {
				if (a[i].first + a[j].first >= p || i == j) continue;
				b[a[i].second] = a[i].first + a[j].first;
				break;
				//b[j] = max(b[j], b[i]);
			}
			if (b[a[i].second] == -1) {
				int t = n - 1;
				if (i == t) t = n - 2;
				b[a[i].second] = (a[i].first + a[t].first) % p;
			}
		}
		printf("%lld", b[0]);
		for (int i = 1; i < n; i ++) printf(" %lld", b[i]);
		printf("\n");
	}

	return 0;
}

 

D - Counting Test (前缀和)

Yousef has a string s that is used to build a magical string w by repeating the string s infinitely many times. For example, if s = aabbb , then w = aabbbaabbbaabbbaabbb....

Mohammad always claims that his memory is strong, and that his ability to count is very high, so Yousef decided to hold a test for Mohammad, in order to know the truth of his claims.

Yousef will give Mohammad q queries, such that each query consisting of two integers l and r, and a lowercase English letter c. The answer of each query is how many times the letter c appears between the lth and rth letters in string w.

Mohammad must answer all the queries correctly, in order to proof his claims, but currently he is busy finishing his meal. Can you help Mohammad by answering all queries?

Input

The first line contains an integer T, where T is the number of test cases.

The first line of each test case contains two integers n and q (1 ≤ n ≤ 104) (1 ≤ q ≤ 105), where n is the length of string s, and q is the number of queries.

The second line of each test case contains the string s of length n consisting only of lowercase English letters.

Then q lines follow, each line contains two integers l and r and a lowercase English letter c (1 ≤ l ≤ r ≤ 109), giving the queries.

Output

For each query, print a single line containing how many times the letter c appears between the lth and rth letters in string w.

Example

Input

1
8 5
abcabdca
1 8 c
1 15 b
4 9 a
5 25 d
2 7 c

Output

2
4
3
3
2

Note

As input/output can reach huge size it is recommended to use fast input/output methods: for example, prefer to use scanf/printf instead of cin/cout in C++, prefer to use BufferedReader/PrintWriter instead of Scanner/System.out in Java.

 解题思路:先用暴力算出每个字母出现次数的前缀和,再计算,计算时先求出必定完整的一段,再加上最前和最后两端。

AC代码:

#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <cstring>
#include <vector>
#include <cstdio>
using namespace std;
#define ll long long 
const int N = 1e4+100;
char s[N];
int a[26][N];
//vector<int>a[26];

int main(){
    int t;
    scanf("%d", &t);
    while (t --) {
        int n, m;
        memset(a, 0, sizeof(a));
        //cin >> n >> m >> s + 1;
        scanf("%d %d %s", &n, &m, s+1);
        for (int i = 1; i <= n; i ++) {
            a[s[i] - 'a'][i] = 1;
        }
        for (int i = 0; i < 26; i ++) {
            for (int j = 1; j <= n; j ++) {
                a[i][j] = a[i][j - 1] + a[i][j];
            }
        }
        while (m --) {
            ll l, r, ql, qr;
            char c;
            //cin >> l >> r >> c;
            scanf("%lld %lld", &l, &r);
            getchar();
            scanf("%c", &c);
            ll ans = (r / n * n - (l + n - 1) / n * n) / n * a[c - 'a'][n];
            ans += a[c - 'a'][n] - a[c - 'a'][(l % n == 0? n : l % n) - 1];
            ans += a[c - 'a'][r % n];
            printf("%lld\n", ans);
        }
    }

    return 0;
}

E - Game of Dice (折半搜索 + 逆元)

It is always fun to play with dice, here is one interesting game:

You are given n fair dice with 6 faces, the faces does not necessarily have values from 1 to 6 written on them. instead, they can have any values from 1 to 100 written on them.

Suppose you threw the n dice one after another, let us define the result of the throws as the multiplication of the numbers you get from each dice mod 109 + 7.

You task is to find how many different ways you can get the result of the dice throws equal to x.

Input

The first line contains an integer T, where T is the number of test cases.

The first line of each test case contains two integers n and x (1 ≤ n ≤ 14) (0 ≤ x < 109 + 7), where n is the number of the dice and x is the required result from the throws.

Then n lines follow, the ith line contains 6 integers fi1, fi2, ..., fi6 (1 ≤ fij ≤ 100), giving the values of ith dice's faces.

Output

For each test case, print a single line containing how many different ways you can get the result of the dice throws equal to x

Example

Input

3
3 9
1 2 3 4 5 6
1 2 3 4 5 6
1 2 3 4 5 6
5 6
1 2 9 9 9 9
1 2 9 9 9 9
1 3 9 9 9 9
1 3 9 9 9 9
1 6 9 9 9 9
5 999999937
100 1 1 1 1 1
100 1 1 1 1 1
100 1 1 1 1 1
100 1 1 1 1 1
100 1 1 1 1 1

Output

3
5
1

 解题:把分成两段搜索,两个数相乘取余后等于x,知道一个数求另一个数就需要用到逆元。

AC代码:

#include <iostream>
#include <algorithm>
#include <map>
using namespace std;

#define ll long long
const int N = 15;
const int p = 1e9 + 7;
int a[N][7];
int n, x;
map<ll, int>m;
ll ans;

void dfs(int st, int ed, ll t) {
	if (st == ed) {
		m[t]++;
		return;
	}
	for (int i = 0; i < 6; i++) {
		ll q = t * a[st][i] % p;
		dfs(st + 1, ed, q);
	}
}

ll Find(ll a, ll t) {
	ll ret = 1;
	while (t) {
		if (t & 1) ret = ret * a % p;
		t >>= 1;
		a = a * a % p;
	}
	return ret % p;
}

void dfs2(int st, int ed, ll t) {
	if (st == ed) {
		ll c = Find(t, p - 2);
		ans += m[x * c % p];
		return;
	}
	for (int i = 0; i < 6; i++) {
		ll q = t * a[st][i] % p;
		dfs2(st + 1, ed, q);
	}
}

int main() {
	int t;
	scanf("%d", &t);
	while (t--) {
		scanf("%d%d", &n, &x);
		m.clear();
		for (int i = 0; i < n; i++)
			for (int j = 0; j < 6; j++)
				scanf("%d", &a[i][j]);
		ans = 0;
		dfs(0, n / 2, 1);
		dfs2(n / 2, n, 1);
		printf("%lld\n", ans);
	}
	return 0;
}

F - Strings and Queries (待补)

You are given a set of n strings such that all characters in the strings are 'a', 'b', or 'c'.

Also, you are given q queries, such that each query consisting of two strings a and b. The answer of each query is the index of the string with the most number of palindrome substrings between strings a and b from the given set.

A substring of the string s is a sequence slsl + 1, ..., sr for some integers (l, r) such that (1 ≤ l ≤ r ≤ n), where n is the length of the string s.

A palindrome is a word, phrase, number, or other sequence of characters which reads the same backward as forward, such as "madam" or "racecar".

Input

The first line contains an integer T, where T is the number of test cases.

The first line of each test case contains two integers n and q (1 ≤ n ≤ 104) (1 ≤ q ≤ 105), where n is the number of strings, and q is the number of queries.

Then n lines follow, each line contains a non-empty string with length no more than 30, giving the strings. All characters in the strings are 'a', 'b', or 'c'. It is guaranteed that all strings are unique. The given strings are numbered from 1 to n.

Then q lines follow, each line contains two strings a and b, giving the queries. It is guaranteed that strings a and b exist in the given set of strings.

Output

For each query, print a single line containing the index of the string with the most number of palindrome substrings between the given strings a and b. If there are more than one answer, print the lowest index.

Example

Input

1
5 5
aaaaa
abaabc
cbbaca
abccba
abca
aaaaa abca
cbbaca abccba
abaabc abccba
abccba abca
abaabc abccba

Output

1
4
2
4
2

Note

As input/output can reach huge size it is recommended to use fast input/output methods: for example, prefer to use scanf/printf instead of cin/cout in C++, prefer to use BufferedReader/PrintWriter instead of Scanner/System.out in Java.

 G - Magical Indices

Alaa sometimes feels bored at work, so at such times she starts playing with a beautiful array a consisting of n integers a1, a2, ..., an.

Alaa starts counting the number of magical indices in the array a. An index x is said to be magical if it satisfying the following rules:

  1. 1 < x < n
  2. ay ≤ ax, for each y (1 ≤ y < x).
  3. ax ≤ az, for each z (x < z ≤ n).

Can you help Alaa by counting the number of magical indices in the array a.

Input

The first line contains an integer T, where T is the number of test cases.

The first line of each test case contains an integer n (1 ≤ n ≤ 106), where n is the size of the array a.

The second line of each test case contains n integers a1, a2, ..., an (1 ≤ ai ≤ 106), giving the array a.

Output

For each test case, print a single line containing the number of magical indices in the array a.

Example

Input

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

Output

3
1

Note

As input/output can reach huge size it is recommended to use fast input/output methods: for example, prefer to use scanf/printf instead of cin/cout in C++, prefer to use BufferedReader/PrintWriter instead of Scanner/System.out in Java.

解题思路:找到有多少个数, 在数组中前面的数都比他大后面的数都比他小,用一个数记录左边最大的数,然后开个数组记录每个右边到某个位置为止最小的数(差点超时了)

AC代码:

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

#define ll long long
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
const int N = 1e6+10;

int a[N];
int b[N];
int main(){
	int t;
	scanf("%d", &t);
	while (t --) {
		int n;
		scanf("%d", &n);
		for (int i = 1; i <= n; i ++) scanf("%d", &a[i]);
		int left = a[1];
		left = a[1];
		int ans = 0;
		b[n] = a[n];
		for (int j = n - 1; j >= 1; j --) {
			b[j] = min(b[j + 1], a[j + 1]);
		}
		for (int i = 2; i <= n - 1; i ++) {
			if (left <= a[i] && a[i] <= b[i]){
				ans ++;
			}
			if (a[i] > left) left = a[i];
		}
		printf("%d\n", ans);
	}

	return 0;
}

 

H - Magical Indices

Husam has a lot of free time, so he is using this time in repairing corrupted binary images.

A Binary image can be represented as 2-dimensional array consisting of n rows, each of which is divided into m columns. The rows are numbered from 1 to n from top to bottom, and the columns are numbered from 1 to m from left to right. Each cell is identified by a pair (xy), which means that the cell is located at row x and column y. The possible values in the binary images are either zero or one.

A binary image is good if all cells in the first row, last row, first column, and last column are ones. Otherwise, the binary image is corrupted. If the binary image is corrupted, Husam will fix it.

Husam wants to fix the image with the minimum number of moves, such that in each move he can swap the values at two different cells.

Can you help Husam by calculating the minimum number of required moves to fix the image?

Input

The first line contains an integer T, where T is the number of test cases.

The first line of each test case contains two integers n and m (3 ≤ n, m ≤ 50), where n is the number of rows in the binary image, and m is the number of columns in each row.

Then n lines follow, each line contains m characters, giving the binary image. All values in the binary image are either zero or one.

Output

For each test case, print a single line containing -1 if Husam cannot fix the binary image. Otherwise, print the minimum number of required moves to fix the image.

Example

Input

3
3 3
111
101
111
4 4
1111
0111
1000
1111
4 5
10101
01010
10101
01010

Output

0
2
-1

Note

In the first test case, the image is good. In the second test case, Husam needs to swap the values of cells (2, 1) and (2, 2), and swap the values of cells (2, 3) and (3, 4), in order to fix the image.

解题思路:主要注意是矩形不是正方形(哭),只有数字1的个数大于等于边长就数边上有多少个0,否则输出-1.

AC代码:

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

#define ll long long
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
const int N = 1e5+10;
const int p = 1e9+7;
int a[N];
int main(){
	//IOS
	int t;
	cin >> t;
	while (t --) {
		int n, m;
		cin >> n >> m;
		string s;
		ll num = 0;
		ll ans = 0;
		ll r = 0;
		for (int i= 0; i < n; i++) {
			s = "";
			cin >> s;
			for (int j = 0; j < m; j ++) {
				if (s[j] == '1') {
					num ++;
					//if (0 < i && i < n - 1 && 0 < j && j < m - 1) ans ++;
					if (i == 0 || i == n - 1 || j == 0 || j == m - 1) r++;
				} 
			}
		}
		if (num < (n * 2 + m * 2 - 4)) //cout << "-1\n";
			cout <<"-1\n";
		else{ 
			ans = n * 2 + m * 2 - r - 4;
			cout << ans << '\n';
		}
	}

	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值