Loading

[记录]2020CCPC网络赛

2020CCPC网络赛(部分题解)

在队友的帮助摸了4道比较简单的题,1002读懂题意知道了怎么做,无奈n太大无法处理素数(知识盲区,不会Min25筛),1005没有分辨出是nim博弈,还是太菜了~~。

持续更新中

1002 Graph Theory Class


题目链接

待更新

题意:

思路:分段打表或min25筛



1003 Express Mail Taking


题目链接

挺水的,不过感觉题目意思有点歧义(只需要去K号柜子一次即可),而且读错题意写出来的代码还能错样例就有点裂开。

题意:n个柜子排成一排,每个柜子之间间距为1,其中m个柜子存放快递,第k号柜子比较特殊,不存放快递,但是取其他柜子的快递需要来k号柜子输入密码打开相应的柜子(类似蜂巢的中控区)。从1号柜子出发,取完所有的快递后需要返回到1号柜子,求最短的距离。

思路:简单贪心。对于不同的走法,每次从k号柜子出发去相应柜子拿快递的距离都是固定的,那么最后总距离的区别就在于从最后一件快递所在的柜子返回到1号柜子。那么只需要最后一件快递离1号柜子最近即可,最后再加上从1前往k的区里即可。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<string>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<vector>
#include<stdlib.h>
#include<time.h>
#include<fstream>
#define mmset(a, b) memset(a, b, sizeof(a))
#define FO(a, b, c) for(int a = b;a < c;a++)
#define FOR(a, b, c) for(int a = b;a <= c;a++)
#define ROF(a, b, c) for(int a = b;a >= c;a--)
#define vi vector<int>
using namespace std;
typedef long long ll;

void FIO()
{
    // #ifndef ONLINE_JUDGE
    // freopen("D:/Code/CC++/in.txt","r", stdin);
    // freopen("D:/Code/CC++/out.out","w", stdout);
    // #endif
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
}
inline int read(){
    int 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;
}

const int M = 1e6 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const int dir[4][2]={1,0, 0,1, -1,0, 0,-1};//上、右、下、左四个方向
int a[M];

int main()
{
    FIO();
    int t, n, m, k;
    cin >> t;
    while(t--){
        cin >> n >> m >> k;
        FOR(i, 0, m-1)
            cin >> a[i];
        sort(a, a+m);
        ll ans = k - 1;
        ROF(i, m-1, 1){
            ans += 2 * abs(k - a[i]);
        }
        ans += abs(k - a[0]) + a[0] - 1;
        /*偷懒直接用了sort对柜子序号排序。可以不用排序的写法如下:
        ll ans = 0;
        int minn = inf;		//记录离1最近的柜子
        FOR(i, 0, m-1){
        	ans += 2 * abs(k - a[i]);
        	minn = min(minn, a[i]);
        }
        ans += 2 * (k - 1);
        ans -= 2 * max(0, k - minn);
        */
        cout << ans << endl;
    }
    //cout << setiosflags(ios::fixed) << setprecision(2) << ans << endl;    //c++控制小数点位数
    //system("pause");
    return 0;
}

1005 Lunch


题目链接

待更新

题意:

思路:nim博弈


1007 CCPC Training Class


题目链接

有CF内味儿了,只要读懂了题就能解,害。

题意:对于一个字符串\(s = s_1s_2s_3\cdots s_n\),用\(s[l:r]\)表示从\(s_l\)\(s_r\),当\(l>r\)时,\(s[l:r]\)为空。定义一个函数\(Lborder_i = max\{0 \le j < i|s[1:j] = s[i-j+1:i]\}\),定义\(D(s) = D(Lborder_i) + 1\),当s为空时,\(D(s) = 0\)
给定一个字符串,可以对其进行重排,令\(W = \max_{i=0}^{n}D(i)\),求W。

思路:看似有点复杂,实际上只是求一个出现最多的字母次数。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<string>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<vector>
#include<stdlib.h>
#include<time.h>
#include<fstream>
#define mmset(a, b) memset(a, b, sizeof(a))
#define FO(a, b, c) for(int a = b;a < c;a++)
#define FOR(a, b, c) for(int a = b;a <= c;a++)
#define ROF(a, b, c) for(int a = b;a >= c;a--)
#define vi vector<int>
using namespace std;
typedef long long ll;
void FIO()
{
    // #ifndef ONLINE_JUDGE
    // freopen("D:/Code/CC++/in.txt","r", stdin);
    // freopen("D:/Code/CC++/out.out","w", stdout);
    // #endif
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
}
inline int read(){
    int 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;
}

const int M = 1e5 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const int dir[4][2]={1,0, 0,1, -1,0, 0,-1};//上、右、下、左四个方向
int a[30];

int main()
{
    FIO();
    string s;
    int t, cnt = 1;
    cin >> t;
    while(t--){
        cin >> s;
        mmset(a, 0);
        int maxn = 0;
        FOR(i, 0, s.size()-1){
            a[s[i] - 'a']++;
        }
        FOR(i, 0, 26)
            maxn = max(maxn, a[i]);
        cout << "Case #" << cnt++ << ": " << maxn << endl;
    }
    //cout << setiosflags(ios::fixed) << setprecision(2) 
    << ans << endl;    //c++控制小数点位数
    //system("pause");
    return 0;
}

1010 Reports


题目链接

签到题

题意:给定一个长度为n的01串,判断是否有连续的0或1出现,有则输出"NO",否则输出"YES"

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<string>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<vector>
#include<stdlib.h>
#include<time.h>
#include<fstream>
#define mmset(a, b) memset(a, b, sizeof(a))
#define FO(a, b, c) for(int a = b;a < c;a++)
#define FOR(a, b, c) for(int a = b;a <= c;a++)
#define ROF(a, b, c) for(int a = b;a >= c;a--)
#define vi vector<int>
using namespace std;
typedef long long ll;

void FIO()
{
    // #ifndef ONLINE_JUDGE
    // freopen("D:/Code/CC++/in.txt","r", stdin);
    // freopen("D:/Code/CC++/out.out","w", stdout);
    // #endif
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
}
inline int read(){
    int 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;
}

const int M = 1e5 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const int dir[4][2]={1,0, 0,1, -1,0, 0,-1};//上、右、下、左四个方向
int a[55];

int main()
{
    FIO();
    int n, t;
    cin >> t;
    while(t--){
        cin >> n;
        bool flag = 0;
        FOR(i, 0, n-1){
            cin >> a[i];
        }
        FOR(i, 1, n-1){
            if(a[i] == a[i-1]){
                flag = 1;
                break;
            }
        }
        if(flag)
            cout << "NO" << endl;
        else
            cout << "YES" << endl;
    }
    //cout << setiosflags(ios::fixed) << setprecision(2) << ans << endl;    //c++控制小数点位数
    //system("pause");
    return 0;
}

1011 3x3 Convolution


题目链接

在大佬的帮助下解出了这道题。不过有点搞人,题目没有说明要处理行末空格,PE白给了一次。

题意:给定一个\(n*n\)的矩阵A和一个\(3*3\)的矩阵K,矩阵K是一个小数矩阵并且所有元素之和等于1。定义一个函数C(A, K),对于函数函数C(A, K)里的值也是构成一个\(n*n\)的矩阵,其中每一元素为\(C_{x,y} = {\sum_{i=1}^{min(n-x+1,3)}\sum_{j=1}^{min(n-y+1,3)}A_{x+i-1,y+j-1}K_{i,j}}\)。定义\(C^m(A, K) = C(C^{m-1}(A, K), K), C^1(A, K) = C(A, K)\),求\(\lim\limits_{t \rightarrow \infty}C^t(A, K)\)。其中K矩阵会用整数矩阵K'代替,矩阵K和K'的对应关系为:\(K_{i, j} = K'_{i, j} / (\sum_{x = 1}^{3}\sum_{y=1}^{3}K'_{x,y})\)

思路:K是一个小数矩阵,A是一个整数矩阵,并且答案是一个整数矩阵,那么最后求的矩阵的\(C_{1,1}\)一定是整数。简单证明一下,假设A是一个4*4的矩阵,那么\(C_{1,1} = {\sum_{i=1}^{3}\sum_{j=1}^{3}A_{i,j}K_{i,j}}\),画图表示就是:

图片

\(C_{1,1}\)就是矩阵A×矩阵K。

因为要求\(\lim\limits_{t \rightarrow \infty}C^t(A, K)\),就是说矩阵A×矩阵K乘了无数次,那么要让最后求的矩阵的\(C_{1,1}\)是整数,那么\(K_{1,1}\)必定是一个整数。因此只需要判断矩阵K'中大于0的数有多少个,超过1那么就输出\(n*n\)的0矩阵,等于1则输出矩阵A。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<string>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<vector>
#include<stdlib.h>
#include<time.h>
#include<fstream>
#define mmset(a, b) memset(a, b, sizeof(a))
#define FO(a, b, c) for(int a = b;a < c;a++)
#define FOR(a, b, c) for(int a = b;a <= c;a++)
#define ROF(a, b, c) for(int a = b;a >= c;a--)
#define vi vector<int>
using namespace std;
typedef long long ll;

void FIO()
{
    // #ifndef ONLINE_JUDGE
    // freopen("D:/Code/CC++/in.txt","r", stdin);
    // freopen("D:/Code/CC++/out.out","w", stdout);
    // #endif
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
}
inline int read(){
    int 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;
}

const int M = 1e2 + 10;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const int dir[4][2]={1,0, 0,1, -1,0, 0,-1};//上、右、下、左四个方向
int a[M][M];
int b[5][5];

int main()
{
    //FIO();
    int t, n;
    cin >> t;
    while(t--){
        int cnt = 0;
        cin >> n;
        FOR(i, 0, n-1)
            FOR(j, 0, n-1)
                cin >> a[i][j];
        FOR(i, 0, 2){
            FOR(j, 0, 2){
                cin >> b[i][j];
                if(b[i][j])
                    cnt++;
            }
        }
        FOR(i, 0, n-1){
            FOR(j, 0, n-1){
                if(cnt > 1)
                    printf(j == 0?"0":" 0");
                else
                    printf(j == 0?"%d":" %d", a[i][j]);
            }
            printf("\n");
        }
    }
    //cout << setiosflags(ios::fixed) << setprecision(2) << ans << endl;    //c++控制小数点位数
    //system("pause");
    return 0;
}
posted @ 2020-09-21 13:11  哈啤丶  阅读(169)  评论(0)    收藏  举报