acwing第67场周赛

1.火柴棍数字

原题链接:https://www.acwing.com/problem/content/4612/

思路

利用n根火柴拼成最大的数字
数字位数越大,数字的值就越大
1只用两根火柴就可以拼成,所以就看n根火柴可以拼成多少根1
n为偶数:拼成的数字为\(n/2\)
n为奇数:拼成的数字也为\(n/2\)位,但多余出来一根火柴,这时就把这根多余出来的火柴和第一位的两根火柴拼成7即可

即:
n为偶数:\(n/2\)位1
n为奇数:第1位为7加上\(n/2-1\)位1

string构造函数

string( size_type length, char ch )

代码:
	cout << string(5,'c');
显示:
	ccccc
代码
#include<iostream>
#include<cstring>

using namespace std;

int main()
{
    int m,n;
    cin >> m;
    while(m --)
    {
        cin >> n;
        
        if(n % 2)
        {
            cout << '7' + string(n/2 - 1,'1') << endl;
        }
        else cout << string(n/2,'1') << endl;
    }
    
    return 0;
}

2.列表排序

原题链接:https://www.acwing.com/problem/content/4613/

思路

第一种操作:只交换每一行的两个数,每一行只能交换一次
第二种操作:交换两列数,只能进行一次操作

如果只看第一种操作
可以发现,只要一行中不在相应位置上的数的个数超过两个,那就无解,否则肯定有解

我们可以先进行第二种操作,然后去判断第一种操作之后是否有解

进行第二种操作一共有 \(C_{m}^{2} + 1\) 种操作(选两列,或者不交换),数据范围比较小,直接暴力枚举即可

代码
#include<iostream>
#include<algorithm>

using namespace std;

const int N = 25;
int g[N][N];
int n,m;

bool check()
{
    int cnt;
    for(int i = 1; i <= n; i ++)
    {
        cnt = 0;
        for(int j = 1; j <= m; j ++)
        {
            if(g[i][j] != j) cnt ++;
            if(cnt > 2) return false;
        }
    }
    return true;
}

int main()
{
    cin >> n >> m;
    
    for(int i = 1; i <= n; i ++)
    {
        for(int j = 1; j <= m; j ++)
        {
            cin >> g[i][j];
        }
    }
    
    // 枚举第二种操作
    for(int i = 1; i <= m; i ++)
    {
        for(int j = i; j <= m; j ++)
        {
            for(int k = 1; k <= n; k ++) swap(g[k][i],g[k][j]);
            if(check()) 
            {
                puts("YES");
                return 0;
            }
            for(int k = 1; k <= n; k ++) swap(g[k][i],g[k][j]); // 一定要记得恢复现场
        }
    }
    puts("NO");
    return 0;
}
posted @ 2022-09-05 11:04  r涤生  阅读(9)  评论(0编辑  收藏  举报