cf思维题

一 Balance the Bits

传送门

A sequence of brackets is called balanced if one can turn it into a valid math expression by adding characters ‘+’ and ‘1’. For example, sequences ‘(())()’, ‘()’, and ‘(()(()))’ are balanced, while ‘)(’, ‘(()’, and ‘(()))(’ are not.

You are given a binary string s of length n. Construct two balanced bracket sequences a and b of length n such that for all 1≤i≤n:

if si=1, then ai=bi
if si=0, then ai≠bi
If it is impossible, you should report about it.

Input
The first line contains a single integer t (1≤t≤104) — the number of test cases.

The first line of each test case contains a single integer n (2≤n≤2⋅105, n is even).

The next line contains a string s of length n, consisting of characters 0 and 1.

The sum of n across all test cases does not exceed 2⋅105.

Output
If such two balanced bracked sequences exist, output “YES” on the first line, otherwise output “NO”. You can print each letter in any case (upper or lower).

If the answer is “YES”, output the balanced bracket sequences a and b satisfying the conditions on the next two lines.

If there are multiple solutions, you may print any.

Example
inputCopy

3
6
101101
10
1001101101
4
1100

outputCopy

YES
()()()
((()))
YES
()()((()))
(())()()()
NO

Note
In the first test case, a="()()()" and b="((()))". The characters are equal in positions 1, 3, 4, and 6, which are the exact same positions where si=1.

In the second test case, a="()()((()))" and b="(())()()()". The characters are equal in positions 1, 4, 5, 7, 8, 10, which are the exact same positions where si=1.

In the third test case, there is no solution.

题意:给出一串二进制的数字(偶数个),要求输入两串字符,1 对应两个字符串相对位置括号方向相同,0 表示两个括号方向不同。要是有符合要求的字符串就输出 YES 在输出两个字符串。否则输出NO;

题解:
首先当 0 的个数为奇数是肯定不可以。首位和末尾不能是 0 .
如果符合就进行构造字符串。
先将首位和末尾看成一对括号,然后遍历一下(去除首尾)如果第一次出现 1 就将两个字符串都加上 ‘( ’ ;第二次加上’)‘循环进行。
如果第一次出现 0 那么就让第一个字符串加上’)‘,第二个加上’(‘,第二次相反,逐渐循环。

AC:

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;
bool solve(string s){
    int cnt=0;
    for(int i=0;i<s.size();i++)
        if(s[i]=='0')cnt++;
    if(s[0]=='0'||cnt%2==1||s[s.size()-1]=='0'){//不符合要求
        return false;
    }
    return true;
}
int main()
{
    int t,n;
    cin >> t;
    while(t--){
        string s="",str1="",str2="";
        cin >> n >> s;
        if(solve(s)){
            str1+='(';str2+='(';   //首
            int flag1=1,flag2=1;
            for(int i=1;i<s.size()-1;i++){//遍历一遍
                if(s[i]=='1'){
                    if(flag1){
                        str1+='(';
                        str2+='(';
                        flag1=0;
                    }else
                    {
                        str1+=')';
                        str2+=')';
                        flag1=1;
                    }
                }
                if(s[i]=='0'){
                    if(flag2){
                        str1+=')';
                        str2+='(';
                        flag2=0;
                    }
                    else{
                        str1+='(';
                        str2+=')';
                        flag2=1;
                    }
                }
            }
            str1+=')';
            str2+=')';   //尾
            cout << "YES" << endl;
            cout << str1 << endl << str2 << endl;
        }else
        {
            cout << "NO" << endl;
        }

    }
    return 0;
}

刚开始刷cf上的思维题,不经感到自己的弱小。。。。

二:
B. M-arrays
You are given an array a1,a2,…,an consisting of n positive integers and a positive integer m.

You should divide elements of this array into some arrays. You can order the elements in the new arrays as you want.

Let’s call an array m-divisible if for each two adjacent numbers in the array (two numbers on the positions i and i+1 are called adjacent for each i) their sum is divisible by m. An array of one element is m-divisible.

Find the smallest number of m-divisible arrays that a1,a2,…,an is possible to divide into.

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

The first line of each test case contains two integers n, m (1≤n≤105,1≤m≤105).

The second line of each test case contains n integers a1,a2,…,an (1≤ai≤109).

It is guaranteed that the sum of n and the sum of m over all test cases do not exceed 105.

Output

For each test case print the answer to the problem.

inputCopy

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

outputCopy

3
6
1
1

Note
In the first test case we can divide the elements as follows:

[4,8]. It is a 4-divisible array because 4+8 is divisible by 4.
[2,6,2]. It is a 4-divisible array because 2+6 and 6+2 are divisible by 4.
[9]. It is a 4-divisible array because it consists of one element.
解题思路:

将每个数进行取余操作,统计数量。
例一:
余数为 0 的有 4 8 所以 vis[0]=2;
余数为 2 的有 2 2 6 所以vis[2]=3;
余数为 1 的有 9 所以vis[1]=1;
我们知道如果两个数相加可以被一个数整除,那么他们对该数取余值的和也可以被整除。
1、余数为 0 的全为一组;
2、如果 i 和 m-i 的个数不同时,我们就取两个数的差值为组数;
如:对 5 取余,有 余数 1 的个数为 2 余数4 的个数为 3 那么最少可以为 1 组
如果余数 4 的个数为 4 那么 最好的结果就是 4 1 4 1 4 ,以及一个 4 单独为一组。

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

const int N=1e5+10;
int vis[N];

int main()
{
    int t,n,m,x;
    cin >> t;
    while(t--){
        memset(vis,0,sizeof(vis));
        cin >> n >> m;
        for(int i=0;i<n;i++){
            cin >> x;
            vis[x%m]++;
        }
        int ans=0;
        if(vis[0])ans++;
        for(int i=1;i<=m/2;i++){
            if(vis[i]&&vis[i]==vis[m-i]){
                ans++;
            }
            else
                ans+=abs(vis[i]-vis[m-i]);
        }
        cout << ans << endl;
    }
    return 0;
}

k-LCM (easy version)
It is the easy version of the problem. The only difference is that in this version k=3.

You are given a positive integer n. Find k positive integers a1,a2,…,ak, such that:

a1+a2+…+ak=n
LCM(a1,a2,…,ak)≤n2
Here LCM is the least common multiple of numbers a1,a2,…,ak.

We can show that for given constraints the answer always exists.

Input
The first line contains a single integer t (1≤t≤104) — the number of test cases.

The only line of each test case contains two integers n, k (3≤n≤109, k=3).

Output
For each test case print k positive integers a1,a2,…,ak, for which all conditions are satisfied.

Example
inputCopy

3
3 3
8 3
14 3

outputCopy

1 1 1
4 2 2
2 6 6

AC

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

int main()
{
    int t,n,m;
    int a,b,c;
    cin >> t;
    while(t--){
        cin >> n >> m;
        if(n&1){
            a=(n-1)/2;
            c=a;
            b=n-2*a;
        }
        else{
            if(n%4==0){
                a=n/2;
                b=a/2;
                c=a/2;
            }
            else{
                a=(n-2)/2;
                c=a;
                b=n-2*a;
            }
        }
        cout << b << " " << c << " " << a << endl;
    }
    return 0;
}

B. I Hate 1111

传送门
You are given an integer x. Can you make x by summing up some number of 11,111,1111,11111,…? (You can use any number among them any number of times).

For instance,

33=11+11+11
144=111+11+11+11
Input
The first line of input contains a single integer t (1≤t≤10000) — the number of testcases.

The first and only line of each testcase contains a single integer x (1≤x≤109) — the number you have to make.

Output
For each testcase, you should output a single string. If you can make x, output “YES” (without quotes). Otherwise, output “NO”.

You can print each letter of “YES” and “NO” in any case (upper or lower).

Example
inputCopy

3
33
144
69

outputCopy

YES
YES
NO

Note
Ways to make 33 and 144 were presented in the statement. It can be proved that we can’t present 69 this way.

题意:给出一个数字,如果能被11,111,111,1111.。。。。组成就输出“YES”,否则输出“NO”

思路:首先我们要想到 111 之后的数字都可以被 11 、111 组合出来。
如1111=11101;
所以这题就变为了 n = a
11 + b111 ;(记录一个公式:两个互质的数,a、b所组不成的最大数为 ab-a-b);
代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

long long n,m,t,k;
void solve(){
    for(int i=0;i*111<=n;i++){
        if((n-i*111)%11==0){
            cout << "YES" << endl;
            return ;
        }
    }
    cout << "NO" << endl;
    return ;
}
int main(){
    int t;
    cin >> t;
    while(t--){
        cin >> n;
        solve();
    }
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值