Virtual Judge周赛三//2023上半学年//实验体更新ing~

  • A-贪心算法//局部最优,全局Doubt

Problem Statement:

You might have remembered Theatre square from the problem 1A. Now it's finally getting repaved.

The square still has a rectangular shape of n×m meters. However, the picture is about to get more complicated now. Let ai,j be the j-th square in the i-th row of the pavement.

You are given the picture of the squares:

  • if ai,j= "*", then the j-th square in the i-th row should be black;
  • if ai,j= ".", then the j-th square in the i-th row should be white.

The black squares are paved already. You have to pave the white squares. There are two options for pavement tiles:

  • 1×1 tiles — each tile costs x burles and covers exactly 1 square;
  • 1×2 tiles — each tile costs y burles and covers exactly 2 adjacent squares of the same row. Note that you are not allowed to rotate these tiles or cut them into 1×1 tiles.

You should cover all the white squares, no two tiles should overlap and no black squares should be covered by tiles.

What is the smallest total price of the tiles needed to cover all the white squares?

Input

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

The first line of each testcase contains four integers n, m, x and y (1≤n≤100; 1≤m≤1000; 1≤x,y≤1000) — the size of the Theatre square, the price of the 1×1 tile and the price of the 1×2 tile.

Each of the next n lines contains m characters. The j-th character in the i-th line is ai,j, If ai,j= "*", then the j-th square in the i-th row should be black, and if ai,j= ".", then the j-th square in the i-th row should be white.

It's guaranteed that the sum of n×m over all testcases doesn't exceed 105.

Output

For each testcase print a single integer — the smallest total price of the tiles needed to cover all the white squares in burles.

Sample 1

InputcopyOutputcopy
4
1 1 10 1
.
1 2 10 1
..
2 1 10 1
.
.
3 3 3 7
..*
*..
.*.
10
1
20
18

Note

In the first testcase you are required to use a single 1×1 tile, even though 1×2 tile is cheaper. So the total price is 10 burles.

In the second testcase you can either use two 1×1 tiles and spend 20 burles or use a single 1×2 tile and spend 1 burle. The second option is cheaper, thus the answer is 1.

The third testcase shows that you can't rotate 1×2 tiles. You still have to use two 1×1 tiles for the total price of 20.

In the fourth testcase the cheapest way is to use 1×1 tiles everywhere. The total cost is 6⋅3=18

AC Code:

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll; 
const int N=1010;
char s[N];
int m,n,x,k,t,y;
int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n>>m>>x>>y;
        ll sum=0;
        while (n -- )
        {
            for(int j=0;j<m;j++)
          {
              cin>>s[j];//一层一层来
          } 
           
            for(int i=0;i<m;i++)
            {
                 
                if(s[i]=='.')
                {
                    int count=1;
                    int j=i;
                   for(int j=i;j<m;j++)//找到连续一段都是‘.’的,求个数。
                   {
贪心算法来解决问题。对于每一行,从左到右遍历,找到连续的空白单元格,
然后根据不同情况计算需要的瓷砖数量。
                       if(s[j]=='.')
                       {
                           count++;
                           s[j]='*';
                       }
                       else break;
                   }
                     count-=1;
                     ll sum1=0,sum2=0;
                     if(count%2==0)sum1=count/2*y;//第一种情况,全铺成1*2的瓷板
                    else sum1=count/2*y+x;//还剩全铺成1*1的
                     sum2=count*x;//第二种情况,全铺成1*1的
                    sum+=min(sum1,sum2);//找最小的就行
                    i=-1;//从头开始重新扫荡这一层
                }
            }
            
        }
        cout<<sum<<endl;
    }
}


核心贪心算法:
cpp
for(int i = 0; i < m; i ++) {
    if(s[i] == '.') {
        // Find the length of continuous empty cells
        int count = 1;
        for(int j = i + 1; j < m && s[j] == '.'; j++) {
            count++;
            s[j] = '*';
        }
        
        // Calculate the required tiles and update the sum
        // ...
        
        // Reset i to start from the beginning of this row
        i = -1;
    }
}

Wrong answer on test 2 Code: 

#include<bits/stdc++.h>
using namespace std;

int main(){
	int t;
	cin>>t;
	while(t--)
	{
		int n,m,x,y;
		cin>>n>>m>>x>>y;
		string str;
		int cntx=0,cnty=0,sum=0;;
		while(n--)
		{
			cin>>str;
			if(x>=2*y){
				for(int i=0;i<m;i++)
				{
					if(str.substr(i,2)=='..')
					{
						cnty+=y;
	  					str[i]='*';
	  					str[i+1]='*';
					}
				}
				for(int i=0;i<m;i++)
				{
					if(str.substr(i,1)=='.')
					{
						cntx+=x;
	  					str[i]='*';
					}
				}
				sum=cntx+cnty;
			}
			else{
				for(int i=0;i<m;i++)
				{
					if(str.substr(i,1)=='.')
					cntx+=x;
				}
				sum=cntx;
			}
		}

		cout<<sum<<endl;
	}
	
	return 0;
}

将贪心算法大大简化但就是通不过test2||系统不兼容

#include<bits/stdc++.h>
using namespace std;
int main(){
	int t;
	cin>>t;
	while(t--){
		int n,m,x,y;
		cin>>n>>m>>x>>y;
		string str;
		long long sum=0,sum1=0,sum2=0;
		while(n--){
			cin>>str;
				int cnt=0;
				for(int i=0;i<m;i++){
					if(str.substr(i,2)=='..'){
	  					cnt+=2;
                        i++;
					}
                    else if(str[i]=='.') cnt++;
				}
			    if(cnt%2==0)sum1=cnt/2*y;
				else sum1=cnt/2*y+x;
				sum2=cnt*x;
				sum+=min(sum1,sum2);
		}
		cout<<sum<<endl;
	}
	return 0;
}

AC Code:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
	int t, r, c, i, j, k, p, s, x, y;
	scanf("%d", &t);
	while (t--)
	{
		scanf("%d %d %d %d", &r, &c, &x, &y);
		char n[101][1001];
 
		for (i = 0; i < r; i++)
		{
			scanf("%s", n[i]);
		}
		s = 0;
		for (i = 0; i<r; i++)
		{
			for (j = 0; j<c; j++)
			{
				if (n[i][j] == '.')
				{
					if (j<c - 1 && n[i][j + 1] == '.')
					{
						if (x * 2 > y)
						{
							s = s + y;
							j++;
						}
						else
						{
							s = s + (x * 2);
							j++;
						}
					}
					else
					{
						s = s + x;
					}
				}
			}
		}
		printf("%d\n", s);
	}
	return 0;
}

  • B-题多

Promble statement:

The Sticker Album of the ICPC 2020 Nlogonian Subregional just came out! Competitive programming hooligans all over the country are buying albums and collecting stickers, to celebrate the competition.

This sticker album is special because all stickers are equal: a picture of this year's trophy. To complete the album, you just need to collect enough stickers to fill all the slots in it.

You may be asking yourself: where is the fun in collecting those stickers? Well, to make things interesting, the stickers are sold in packets, each with a random number of stickers! Fans celebrate when they find a high number of stickers in a packet, make fun of those who got unlucky and found low numbers of stickers, and brag about filling their whole albums with just a few packets.

You just acquired your own album, and want to start filling it! But before buying your first sticker packets, you wondered: on average, how many packets does one need to buy in order to fill an album?

Input

The only input line contains three integers N, A and B, separated by a single space, satisfying 1≤N≤10e+6, 0≤A≤B≤10e+6 and B>0, where:

  • N is the number of stickers it takes to fill an album;
  • A is the minimum number of stickers in a packet;
  • B is the maximum number of stickers in a packet.

The number of stickers in each packet is uniformly distributed in the closed interval [A,B].

Output

The output consists of a single line, which must contain the expected number of packets it takes to complete an album. The number will be considered correct if it is within an absolute or relative error of 10−510−5 of the correct answer.

Sample 1

InputcopyOutputcopy
40 0 2
40.33333

Sample 2

InputcopyOutputcopy
100 1 10
18.72727

Sample 3

InputcopyOutputcopy
30 3 3
10.00000

Sample 4

InputcopyOutputcopy
314 5 8
48.74556
很显然的一道概率dp题,状态转移方程如下:
d p [ i ] = ( d p [ i + A ] + d p [ i + A + 1 ] + . . . + d p [ i + B ] ) / ( B − A + 1 ) + 1 dp[i]=(dp[i+A]+dp[i+A+1]+...+dp[i+B])/(B-A+1)+1dp[i]=(dp[i+A]+dp[i+A+1]+...+dp[i+B])/(B−A+1)+1
要留意一下当 A = 0 A=0A=0 时候的特判:d p [ i ] = ( d p [ i + A + 1 ] + . . . + d p [ i + B ] + B − A + 1 ) / ( B − A ) dp[i]= (dp[i+A+1]+...+dp[i+B]+B-A+1)/(B-A)dp[i]=(dp[i+A+1]+...+dp[i+B]+B−A+1)/(B−A)
AC Code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e6 + 10;
const int INF = 0x3f3f3f3f;
double dp[N] = { 0 };
int n, A, B;
int main() {
    scanf("%d %d %d", &n, &A, &B);
    if (A == 0) {
        double sum = 0;
        for (int i = n - 1; i >= 0; --i) {
            sum -= dp[i + B + 1];
            sum += dp[i + 1];
            dp[i] = (sum + B - A + 1) / (B - A);
        }
        printf("%.10lf\n", dp[0]);
    }
    else {
        double sum = 0;
        for (int i = n - 1; i >= 0; --i) {
            sum -= dp[i + B + 1];
            sum += dp[i + A];
            dp[i] = sum / (B - A + 1) + 1.0;
        }
        printf("%.10lf\n", dp[0]);
    }
    return 0;
}

AC Code:

#include<bits/stdc++.h>

using namespace std;

using ll = long long;
const int N = 2000010;
int n,A,B;
double dp[N];

void solve(){

    cin >> n >> A >> B;

    dp[0] = 0;
    double l = B - A + 1;
    // for(int i = 0; i <= n; ++i)
    //     for(int j = A; j <= B; ++j)
    //         dp[i + j] += 1.0 / (B - A + 1) * (dp[i] + 1);

    double c = 0;
    if(A){
    for(int i = n - 1; i >= 0; --i){
        //for(int j = A; j <= B; ++j){
            //dp[i] += (dp[i + j] + 1) / l;
            // if(A) dp[i] = c / l + 1;
            // else dp[i] = c / (l - 1) + 1;
            dp[i] = c / l + 1;
            c += dp[i + A - 1], c -= dp[i + B]; 
        }
    }
    else{
        for(int i = n - 1; i >= 0; --i){
            dp[i] = c / (l - 1) + l / (l - 1);
            c += dp[i + A], c -= dp[i + B];
        }
    }
    //cout << dp[3] << "\n";
    cout << fixed << setprecision(10) << dp[0] << "\n";
}

int main(){

    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);        

    int T = 1;
    
    while(T--) solve();

    return 0;
}

AC Code://双指针解决...*...特例如果用上面6得到3个长瓷砖但应该是2个长的两个短的

#include<bits/stdc++.h>
using namespace std;
int main() {
	int t;
	cin>>t;
	while(t--) {
		int n,m,x,y;
		cin>>n>>m>>x>>y;
		string str;
		long long sum=0,sum1=0,sum2=0;

		while(n--) {
			cin>>str;
			sum1 = sum2 = 0;
			for(int k = 0; k < m; ++k) {
				if(str[k] == '*') continue;
				int cnt=0;
				for(int i=k; i<m; i++) {
					k = i;-
					if(str[i] == '.') cnt++;
					else break;
				}
				if(cnt % 2) sum1 += cnt / 2 * y + x;
				else sum1 += cnt / 2 * y;

				sum2 += cnt * x;
			}
			sum+=min(sum1,sum2);
		}
		cout<<sum<<endl;
	}
	return 0;
}
  • C-但是

Proble Statement:

Eugenius is a very bright mathematician who enjoys multiplying numbers.

Once, he found M nodes written on a piece of paper, numbered from 1 to M, we call these M-nodes. Each node i was labeled with a unique prime number pi, such that the primes were ordered (i.e. if i<j then pi<pj).

Later on, he decided to draw N new nodes, called N-nodes, and add edges between nodes in M and nodes in N. He was very careful not to connect an M-node with an M-node, nor an N-node with an N-node; he wasn't as careful regarding how many edges between any two nodes he drew.

And just like that, he ended up with a bipartite multigraph.

As he mainly enjoyed multiplying numbers, he decided to label each N-node with the multiplication of all M-nodes that were directly connected to it; where each M-node was multiplied as many times as edges were between them.

Each N-node i ended up being labeled with a number ci. Then, the following formula characterizes each ci:

ci=∏(j,i)∈E/*这三个元在下面*/pj/*j是一级下标*/,

where E is the multiset of added edges, and every edge e satisfies e∈M×N. Later on, Eugenius decided to grab something to eat. While he was enjoying his torus, he accidentally spilled coffee on the labels pi and they disappeared.

Can you help him recover those sorted prime numbers?

Input

The first line contains three integers M, N and K, the amount of M-nodes, the amount of N-nodes and the amount of distinct edges. These values are such that 1≤M,N<103 and 1≤K≤104.

The next line has N numbers ci (the labels of the N-nodes), such that 1<ci<1015.

Finally, there are K lines, each of these has three numbers m n d, representing that there are d edges between M-node m and N-node n, satisfying 1≤m≤M, 1≤n≤N and 1≤d≤50.

It is guaranteed that all nodes (M-nodes and N-nodes) have degree at least 1.

Output

Output a single line with M sorted numbers, the prime labels of the M-nodes of indices 1,…,M1,…, that keep Eugenius awake.

Sample 1

InputcopyOutputcopy
4 3 4
15 16 13
2 1 1
3 1 1
1 2 4
4 3 1
2 3 5 13

Sample 2

InputcopyOutputcopy
4 5 7
3 9 7 143 143
1 1 1
1 2 2
2 3 1
3 4 1
3 5 1
4 5 1
4 4 1
3 7 11 13

Sponsor

经典的树形dp题,首先题目要求在查询量最小的情况下完成操作。可知最小的查询量是叶子结点的数量,可以证明当所有的叶子结点的数量都知道后,整颗树的权值都出来了。
在需要数量是所有叶子结点的情况下,现考虑两个状态,d p [ N ] [ 2 ] dp[N][2]dp[N][2]
若当前点需要查询,则记录为 d p [ i ] [ 1 ] dp[i][1]dp[i][1] ;否则若不需要查询,则记录为 d p [ i ] [ 0 ] dp[i][0]dp[i][0]
当不需要查询的时候,d p [ i ] [ 0 ] = ∏ d p [ v ] [ 0 ] dp[i][0]=\prod dp[v][0]dp[i][0]=∏dp[v][0] ,其中 v vv 是 i ii 的子结点
当需要查询的时候,dp[i][1]=∏dp[ v k ] [ 0 ] ∗ d p [ v j ] [ 1 ] dp[i][1]=\prod dp[v_k][0]*dp[v_j][1]dp[i][1]=∏dp[v 
k][0]∗dp[j][1] ,其中 j ≠ k


最后需要 d p [ i ] [ 0 ] + = d p [ i ] [ 1 ] dp[i][0]+=dp[i][1]dp[i][0]+=dp[i][1] 表示在当前点进行查询; d p [ i ] [ 1 ] dp[i][1]dp[i][1] 表示在当前点未进行查询并且仍欠一个查询。


因为直接对乘数积乘逆元会出错,下面代码采用左右两段来进行乘法运算

AC Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1e3 + 10;
const int INF = 0x3f3f3f3f;
const int M = 31622776 + 10;
inline ll rd() {
    ll x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}
int n, m, k;
int prime[M], cnt = 0;
bool isprime[M];
void init() {
    for (int i = 2;i <= M - 10;++i) {
        if (!isprime[i]) prime[++cnt] = i;
        for (int j = 1;j <= cnt && prime[j] * i <= M - 10;++j) {
            isprime[i * prime[j]] = true;
            if (i % prime[j] == 0) break;
        }
    }
}
ll c[N];
struct node {
    ll id, cnt;
    node(ll id = 0, ll cnt = 0) :id(id), cnt(cnt) {}
    bool friend operator<(const node& a, const node& b) {
        return a.cnt < b.cnt || a.cnt == b.cnt && a.id < b.id;
    }
};
vector<node>vec[N];
vector<node>G[N];
ll p[N];
int main() {
    init();
 //   scanf("%d %d %d", &m, &n, &k);
    m = rd(), n = rd(), k = rd();
    set<int>s;
    for (int i = 1;i <= m;++i) s.insert(i);
    for (int i = 1;i <= n;++i) c[i] = rd();
    for (int i = 1;i <= k;++i) {
        int x, y, d;x = rd(), y = rd(), d = rd();
        vec[y].push_back(node(x, d));
    }
    for (int i = 1;i <= n;++i) {
        ll tmp = c[i];
        G[i].resize(vec[i].size());int pos = 0;
        for (int j = 1;j <= cnt && 1LL * prime[j] * prime[j] <= tmp;++j) {
            if (tmp % prime[j] == 0) {
                int tot = 0;
                while (tmp % prime[j] == 0) tmp /= prime[j], ++tot;
                G[i][pos++] = (node(prime[j], tot));
            }
        }
        if (tmp > 1) G[i][pos++] = (node(tmp, 1));
        sort(vec[i].begin(), vec[i].end());
        sort(G[i].begin(), G[i].end());
        for (int j = 0;j < vec[i].size();++j) {
            p[vec[i][j].id] = G[i][j].id;
            auto v = s.find(vec[i][j].id);
            if (v != s.end()) s.erase(v);
        }
        if (s.empty()) break;
    }
    for (int i = 1;i <= m;++i) printf("%lld%s", p[i], i == m ? "\n" : " ");
    return 0;
}
  • D-签到

Problem statement:

Battleship is a classic strategy game for two players. Each player places his set of ships in a 10×1010×10 grid and then games consist of guessing positions of ships. The actual game rules are not important for this problem, and many variations exist, but here we are interested on a much more basic problem. Given the lists of ships and their positions, your task is to check whether the initial positioning is valid.

The grid rows and columns are numbered from 11 to 1010, and ships are positioned horizontally or vertically, occupying a contiguous sequence of squares of the board. For this problem, a positioning is valid if

  • No position is occupied by more than one ship;
  • All the ships are totally contained inside the board.

Input

The first line of the input contains an integer N, 1≤N≤100 the number of ships. Each of the next N lines contain four integers D, L, R and C with D∈{0,1}, 1≤L≤5 and 1≤R,C≤10 describing a ship. If D=0 then the ship is aligned horizontally, and occupy positions (R,C)…(R,C+L−1). Otherwise the ship is aligned vertically, occupying positions (R,C)…(R+L−1,C).

Output

Output a single line containing a single character. If the initial positioning of the ships is valid, then write the upper case letter 'Y'; otherwise write the uppercase letter 'N'.

Sample 1

InputcopyOutputcopy
3
0 5 1 1
1 5 2 2
0 1 3 3
Y

Sample 2

InputcopyOutputcopy
2
0 2 1 1
1 1 1 2
N

Sample 3

InputcopyOutputcopy
1
0 2 10 10
N

Sample 4

InputcopyOutputcopy
7
0 3 2 2
1 5 2 9
1 2 3 6
1 1 4 2
0 1 6 6
0 4 8 4
0 2 10 1
Y
AC Code:
#include<bits/stdc++.h>
using namespace std;


int main(){
	char q[12][12];
	for(int i=1;i<=10;i++)
		for(int j=1;j<=10;j++)
		q[i][j]='.';
	int N;
	cin>>N;
	int sum=0;
	while(N--)
	{   int D,L,R,C;
		cin>>D>>L>>R>>C;
		sum+=L;
		if(D==0)
		{   for(int i=C;i<=C+L-1;i++)
			{   if(q[R][i]=='.')
				q[R][i]='*';
			}
		}
		if(D==1)
		{
			for(int i=R;i<=R+L-1;i++)
			{
				if(q[i][C]=='.')
				q[i][C]='*';
			}
		}
	}
	int cnt=0;
	for(int i=1;i<=10;i++)
		for(int j=1;j<=10;j++)
		if(q[i][j]=='*')cnt++;
	if(cnt==sum)cout<<"Y";
	else cout<<"N";
	return 0;
}
  • E-题

Problem Statement:

We have a rooted tree with N vertices numbered 1 to N. Vertex 11 is the root of the tree, and the parent of vertex  i (2≤i) is vertex pi​.

Each vertex has a color: black or white. Initially, all vertices are white.

In this rooted tree, vertex i is said to be good when all vertices on the simple path connecting vertices 1 and i (including vertices 1 and i) are black, and bad otherwise.

Until all vertices are black, let us repeat the following operation: choose one vertex from the bad vertices uniformly at random, and repaint the chosen vertex black.

Find the expected value of the number of times we perform the operation, modulo 998244353998244353.

The definition of the expected value modulo 998244353998244353

Constraints

  • 2≤N≤2×10e+5
  • 1≤pi​<i
  • All values in the input are integers.

Input

The input is given from Standard Input in the following format:

N
p2​ p3​ …… pN​

Output

Print the answer.

Sample 1

InputcopyOutputcopy
4
1 1 3
831870300

Consider a case where the first three operations have chosen vertices 11, 22, and 44 in this order. Then, vertices 11 and 22 are good, but vertex 44 is still bad since vertex 33, an ancestor of vertex 44, is white. Thus, the fourth operation will choose vertex 33 or 44 uniformly at random.

The expected value of the number of times we perform the operation is 356635​.

Sample 2

InputcopyOutputcopy
15
1 2 1 1 4 5 3 3 5 10 3 6 3 13
515759610
AC Code:
有待商榷
#include <iostream>
#include <vector>

using namespace std;

const int MOD = 998244353;

vector<vector<int>> tree;
vector<bool> isBlack;
vector<long long> expectedValue;
vector<long long> subtreeSize;

void dfs(int node) {
    // Calculate the expected value and subtree size for each node using DFS
    
    // Initialize expected value and subtree size for the current node
    expectedValue[node] = isBlack[node] ? 0 : 1;
    subtreeSize[node] = 1;
    
    // Traverse all children of the current node
    for (int child : tree[node]) {
        dfs(child);
        subtreeSize[node] += subtreeSize[child];
        expectedValue[node] += (expectedValue[child] + subtreeSize[child]);
    }
    
    // Normalize the expected value modulo MOD
    expectedValue[node] %= MOD;
}

int main() {
    int N;
    cin >> N;
    
    tree.resize(N+1);
    isBlack.resize(N+1, false);
    expectedValue.resize(N+1);
    subtreeSize.resize(N+1);
    
    // Read the parent-child relationships and build the tree
    for (int i = 2; i <= N; i++) {
        int p;
        cin >> p;
        tree[p].push_back(i);
    }
    
    // Set the color of vertices
    for (int i = 1; i <= N; i++) {
        char c;
        cin >> c;
        if (c == '1') {
            isBlack[i] = true;
        }
    }
    
    // Start the DFS from the root node
    dfs(1);
    
    // Print the expected value modulo MOD
    cout << expectedValue[1] << endl;
    
    return 0;
}


上述代码使用深度优先搜索(DFS)计算每个节点的期望值和子树大小。
首先,建立一个表示树的邻接表,并初始化颜色数组。
然后进行DFS遍历,计算每个节点的期望值和子树大小。
对于每个节点,将其子节点的期望值和子树大小相加,并加上子节点本身的期望值和子树大小。
最后,将根节点的期望值取模输出
  • F-也多

Problem statement:

The Commission for the Regional deveLopment of Fastminton (CRLF) organizes annual tournaments of the novel and unusual game of Fastminton, a Badminton derivative. CRLF is proud to be organizing the third big tournament, that will be held this year.

The commission's former programmer has developed a computerized system to capture and store the results from the matches, point by point, to individual files. He left before being able to complete a parser to the files, so the CRLF requires your help to guarantee that all the records can be read from the written files, to avoid loosing years of thrilling game results.

A summary of the Fastminton rules was given to you to help in your tasks. It is, in essence, a shorter (or faster) version of Badminton:

  • Fastminton matches are always played with two opposing players in a court that is divided by a net;
  • Players are identified by their relative positions on the score (left and right player);
  • A match is composed of three games. The player that reaches 22 games is the winner;
  • A game is won when a player reaches at least 55 points with a at least a 22 point difference from his opponent, or by reaching 1010 points (whichever comes first);
  • The left player begins serving on the first game. For all other games, the serving player is the one that won the last game;
  • Every round results in a point for the server or the receiver player. The player who scores serves the next round.

Input

The input is comprised of a single line containing a sequence of characters. This line represents a complete match event sequence, and may contain the characters S (server point), R (receiver point) or Q (score announcement). The input does not contains consecutive score announcements.

Output

The program must print a line containing the current score for each score announcement (Q) found on the input.

If the game is underway, the announcement will be in the format "GL (PL) - GR (PR)", where GL and GR are the number of games won by the left and right players, and PL and PR are the current points of the left and right players. An asterisk (*) must be appended to the point marked of the player that will serve in the next round.

If the game has finished, the announcement will follow "GL - GR" with the string "(winner)" added at the end of the game marked of the winner player.

Sample 1

InputcopyOutputcopy
SRSSQSSSSQRRSS
0 (1) - 0 (3*)
0 (0) - 1 (2*)

Sample 2

InputcopyOutputcopy
SRSSQSSSSQRRSSQ
0 (1) - 0 (3*)
0 (0) - 1 (2*)
0 - 2 (winner)

Sample 3

InputcopyOutputcopy
RSRSSRRRRRRRRRRSSSSRRSQ
2 (winner) - 0

Sponsor

AC Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e6 + 10;
const int INF = 0x3f3f3f3f;
char s[N];
int main() {
    scanf(" %s", s + 1);
    int len = strlen(s + 1);
    bool flag = false;
    int ls = 0, rs = 0, RS = 0, LS = 0;
    int win = 0;
    for (int i = 1; i <= len; ++i) {
        if (!flag) {
            if (s[i] == 'S') {
                ++ls;
            }
            else if (s[i] == 'R') {
                ++rs;
                flag = true;
            }
            bool win = false;
            if (ls >= 5 && ls - rs >= 2 || ls >= 10) {
                ++LS;
                ls = rs = 0;
            }
            else if (rs >= 5 && rs - ls >= 2 || rs >= 10) {
                ++RS;
                ls = rs = 0;
            }
            if (win == 0) {
                if (LS >= 2)
                    win = 1;
                else if (RS >= 2)
                    win = 2;
            }
            if (s[i] == 'Q') {
                if (win == 1)
                    printf("%d (winner) - %d\n", LS, RS);
                else if (win == 2)
                    printf("%d - %d (winner)\n", LS, RS);
                else {
                    if (!flag) 
                        printf("%d (%d*) - %d (%d)\n", LS, ls, RS, rs);
                    else
                        printf("%d (%d) - %d (%d*)\n", LS, ls, RS, rs);
                }
            }
        }
        else {
            if (s[i] == 'S') {
                ++rs;
            }
            else if (s[i] == 'R') {
                ++ls;
                flag = false;
            }
            if (ls >= 5 && ls - rs >= 2 || ls >= 10) {
                ++LS;
                ls = rs = 0;
            }
            else if (rs >= 5 && rs - ls >= 2 || rs >= 10) {
                ++RS;
                ls = rs = 0;
            }
            if (win == 0) {
                if (LS >= 2)
                    win = 1;
                else if (RS >= 2)
                    win = 2;
            }
            if (s[i] == 'Q') {
                if (win == 1)
                    printf("%d (winner) - %d\n", LS, RS);
                else if (win == 2)
                    printf("%d - %d (winner)\n", LS, RS);
                else {
                    if (!flag)
                        printf("%d (%d*) - %d (%d)\n", LS, ls, RS, rs);
                    else
                        printf("%d (%d) - %d (%d*)\n", LS, ls, RS, rs);
                }
            }
        }
    }
    return 0;
}
  • G-思维

Problem statement;

You are given a string s, consisting of brackets of two types: '(', ')', '[' and ']'.

A string is called a regular bracket sequence (RBS) if it's of one of the following types:

  • empty string;
  • '(' + RBS + ')';
  • '[' + RBS + ']';
  • RBS + RBS.

where plus is a concatenation of two strings.

In one move you can choose a non-empty subsequence of the string s (not necessarily consecutive) that is an RBS, remove it from the string and concatenate the remaining parts without changing the order.

What is the maximum number of moves you can perform?

Input

The first line contains a single integer t (1≤t≤1000) — the number of testcases.

Each of the next t lines contains a non-empty string, consisting only of characters '(', ')', '[' and ']'. The total length of the strings over all testcases doesn't exceed 2⋅1052⋅105.

Output

For each testcase print a single integer — the maximum number of moves you can perform on a given string s.

Sample 1

InputcopyOutputcopy
5
()
[]()
([)]
)]([
)[(]
1
2
2
0
1

Note

In the first example you can just erase the whole string.

In the second example you can first erase the brackets on positions 11 and 22: "[]()", then "()" is left. After that you can erase it whole. You could erase the whole string from the beginning but you would get one move instead of two.

In the third example you can first erase the brackets on positions 11 and 33: "([)]". They form an RBS "()". Then "[]" is left, so you can erase it whole.

In the fourth example there is no subsequence that is an RBS, so you can't perform a move at all.

In the fifth example you can erase the brackets on positions 22 and 44: ")[(]" and get ")(" as a result. You can erase nothing from it.

AC Code:

#include <bits/stdc++.h>
typedef long long ll;

const ll mod =1e9 + 7;

using namespace std;
namespace fastIO {
    inline void input(int& res) {
        char c = getchar();res = 0;int f = 1;
        while (!isdigit(c)) { f ^= c == '-'; c = getchar(); }
        while (isdigit(c)) { res = (res << 3) + (res << 1) + (c ^ 48);c = getchar(); }
        res = f ? res : -res;
    }
    inline ll qpow(ll a, ll b) {
        ll ans = 1, base = a;
        while (b) {
            if (b & 1) ans = (ans * base % mod +mod )%mod;
            base = (base * base % mod + mod)%mod;
            b >>= 1;
        }
        return ans;
    }
}
using namespace fastIO;

const int N = 2e5+5;
int Case,x,y;
char a[N];
void solve(){
	int ans1 = 0,ans2 = 0,sum = 0;
	scanf("%s",a);
	int len = strlen(a);
	for(int i=0;i<len;i++){
		if(a[i]=='(') ans1++;
		if(a[i]=='[') ans2++;
		if(a[i]==')'&&ans1>0){
			ans1--;
			sum++;
		}
		if(a[i]==']'&&ans2>0){
			ans2--;
			sum++;
		}
	}
	printf("%d\n",sum);
}

int main(){
	Case=1;
	input(Case);
	while(Case--){
		solve();
	}
	return 0;
}
/*
5
5 5
3 4
7 1
0 0
2 0
*/
  • H-也很

Problem statement:

Ashish has two strings a and b, each of length n, and an integer k. The strings only contain lowercase English letters.

He wants to convert string a into string b by performing some (possibly zero) operations on a.

In one move, he can either

  • choose an index i (1≤i≤n−1) and swap ai and ai+1, or
  • choose an index i (1≤i≤n−k+1) and if ai,ai+1,…,ai+k−1 are all equal to some character c (c≠ 'z'), replace each one with the next character (c+1), that is, 'a' is replaced by 'b', 'b' is replaced by 'c' and so on.

Note that he can perform any number of operations, and the operations can only be performed on string a.

Help Ashish determine if it is possible to convert string a into b after performing some (possibly zero) operations on it.

Input

The first line contains a single integer t (1≤t≤10e+5) — the number of test cases. The description of each test case is as follows.

The first line of each test case contains two integers n (2≤n≤10e+6) and k (1≤k≤n).

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

The third line of each test case contains the string b of length n consisting of lowercase English letters.

It is guaranteed that the sum of values n among all test cases does not exceed 106106.

Output

For each test case, print "Yes" if Ashish can convert a into b after some moves, else print "No".

You may print the letters of the answer in any case (upper or lower).

Sample 1

InputcopyOutputcopy
4
3 3
abc
bcd
4 2
abba
azza
2 1
zz
aa
6 2
aaabba
ddddcc
No
Yes
No
Yes

Note

In the first test case it can be shown that it is impossible to convert a into b.

In the second test case,

"abba" −→inc→inc "acca" −→inc→inc …… −→inc→inc "azza".

Here "swap" denotes an operation of the first type, and "inc" denotes an operation of the second type.

In the fourth test case,

"aaabba" −→−−swap→swap "aaabab" −→−−swap→swap "aaaabb" −→inc→inc …… −→inc→inc "ddaabb" −→inc→inc …… −→inc→inc "ddddbb" −→inc→inc …… −→inc→inc "ddddcc".

AC Code:

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
const int maxn = 1e6 + 7;
int a[30],b[30];
char s1[maxn],s2[maxn];
int main() {
    int T;scanf("%d",&T);
    while(T--) {
        int n,k;scanf("%d%d",&n,&k);
        scanf("%s%s",s1 + 1,s2 + 1);
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        for(int i = 1;i <= n;i++) {
            a[s1[i] - 'a']++;
            b[s2[i] - 'a']++;
        }
        int cnt = 0;
        int flag = 1;
        for(int i = 0;i < 26;i++) {
            int num = a[i] - b[i];
            if(num % k != 0) {
                flag = 0;break;
            }
            if(i == 25 && num > 0) {
                flag = 0;break;
            }
            cnt += num / k;
            if(cnt < 0) {
                flag = 0;break;
            }
        }
        if(cnt != 0 || flag == 0) {
            printf("No\n");
        } else {
            printf("Yes\n");
        }
    }
    return 0;
}
  • I-重要

Problem Statement

We define the density of a non-empty simple undirected graph as (number of edges)(number of vertices)(number of vertices)(number of edges)​.

You are given positive integers N and D. Determine whether there is a simple undirected graph G with N vertices and DN edges that satisfies the following condition. If it exists, find one such graph.

Condition: Let V be the vertex set of G. For any non-empty proper subset X of V, the density of the induced subgraph of G by X is strictly less than D.

What is an induced subgraph?

For a vertex subset X of graph G, the induced subgraph of G by X is the graph with vertex set X and edge set containing all edges of G that connect two vertices in X. In the above condition, note that we only consider vertex subsets that are neither empty nor the entire set.

Constraints

  • N≥1
  • D≥1
  • DN≤5×10e+4

Input

The input is given from Standard Input in the following format:

N D

Output

If there is a simple undirected graph that satisfies the condition, print Yes; otherwise, print No. Furthermore, in the case of Yes, print a graph that satisfies the condition in the following format in the next DN lines. If multiple graphs satisfy the condition, any of them will be considered correct.

A1​ B1​
A2​ B2​
⋮
ADN​ BDN​/*DN都是下标*/
  • 1≤Ai​,Bi​≤N  (1≤i≤DN)
  • Ai​≠Bi​  (1≤i≤DN)
  • {Ai​,Bi​}≠{Aj​,Bj​}  (1≤i<j≤DN)
  • The vertices of the graph are numbered from 1 to N.
  • The i-th line of the output represents that the i-th edge connects vertex Ai​ and vertex Bi​.
  • The order of the edges (which edge is printed first) and the order of the vertices (which endpoint of each edge is printed first) may be arbitrary.

Sample 1

InputcopyOutputcopy
3 1
Yes
1 2
1 3
2 3

The printed graph has vertex set {1,2,3}{1,2,3} and edge set {(1,2),(1,3),(2,3)}{(1,2),(1,3),(2,3)}, and is simple. The vertex set X has 66 non-empty proper subsets: {1},{2},{3},{1,2},{1,3},{2,3}{1},{2},{3},{1,2},{1,3},{2,3}.

  • For X={1},{2},{3}, the edge sets of the induced subgraphs by X are empty, and the densities are 01=010​=0.
  • For X={1,2},{1,3},{2,3}, the edge sets of the induced subgraphs by X are {(1,2)},{(1,3)},{(2,3)}{(1,2)},{(1,3)},{(2,3)}, respectively, and the densities are all 1/2.

In all cases, the density of the induced subgraph is strictly less than D=1, so this graph satisfies the condition.

Sample 2

InputcopyOutputcopy
4 2
No

A simple undirected graph with 44 vertices and 88 edges does not exist.
Sponsor

AC Code:

有待商榷
#include <iostream>
#include <vector>

using namespace std;

bool checkGraph(int N, int D) {
    // Check if a simple undirected graph with N vertices and DN edges satisfies the condition
    
    // Calculate the maximum number of edges for the given N and D
    int maxEdges = N * D;
    
    // Check if the maximum number of edges is greater than or equal to N(N-1)/2
    if (maxEdges < N*(N-1)/2) {
        return false; // No graph exists
    }
    
    return true; // Graph exists
}

void generateGraph(int N, int D) {
    // Generate a simple undirected graph with N vertices and DN edges that satisfies the condition
    
    vector<pair<int, int>> edges;
    
    // Generate edges for the graph
    for (int i = 1; i <= N; i++) {
        for (int j = i+1; j <= N; j++) {
            edges.push_back({i, j});
        }
    }
    
    // Print the graph
    cout << "Yes" << endl;
    for (int i = 0; i < D*N; i++) {
        cout << edges[i].first << " " << edges[i].second << endl;
    }
}

int main() {
    int N, D;
    cin >> N >> D;
    
    if (checkGraph(N, D)) {
        generateGraph(N, D);
    } else {
        cout << "No" << endl;
    }
    
    return 0;
}

上述代码用于判断是否存在满足条件的简单无向图,并如果存在,生成一个满足条件的图。
该算法首先通过计算最大边数来判断是否存在满足条件的图。
如果最大边数小于N(N-1)/2,则无法生成满足条件的图。
否则,可以通过遍历所有节点对来生成边,并输出图的边集合
  • J-呢

Problem statement:

An integer x is said to be a right-coupled number, if you can find two integers, say 0≤a≤b≤x such that a×b=x and ab≥0.5. In this problem, your task is to determine whether a given integer is a right-coupled number or not.

Input

The first line of the input is an integer N denoting the number of test cases (1≤N≤1000). Each test case is in one line, which contains a single integer 0<x<215.

Output

If the given integer x is a right-coupled number, output 1; otherwise, output 0. Each is in a single line.

Sample 1

InputcopyOutputcopy
4
66
55
105
150
1
0
0
1
AC Code:
#include<bits/stdc++.h>
using namespace std;
int n;

void solve(){
    scanf("%d",&n);
    for(int i=1;i<=sqrt(n);i++){
        if(n%i==0){
            int a=i,b=n/i;
            if(a>b) swap(a,b);
            if(a*2>=b){
                printf("1\n");
                return ;
            }
        }
    }
    printf("0\n");
}

int main(){
    int te;
    scanf("%d",&te);
    while(te--) solve();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值