2020年湖南省大学生计算机程序设计竞赛

A 2020

一个简单的 DP,f[i]表示前i位最多能选择的子串个数。

转移首先不选可以得到f[i] = f[i-1],其次如果当前的后缀是2020的话就f[i] = max( f[i] , f[i-4]+1)

#include<bits/stdc++.h>

using namespace std;

const int N = 1e5+5;
char s[N];
int f[N];

int32_t main() {
    int n;
    while( cin >> n ){
        f[0] = 0;
        scanf("%s" , s+1 );
        for( int i = 4 ; i <= n ; i ++ ){
            f[i] = f[i-1];
            if( s[i-3] == '2' && s[i-2] == '0' && s[i-1] == '2' && s[i] == '0')
                f[i] = max( f[i] , f[i-4] + 1 );
        }
        int res = 0;
        for( int i = 1 ; i <= n ; i ++ )
            res = max( res , f[n] ) ;
        cout << res <<"\n";
    }

    return 0;
}

B 2020 vs 2018

这道题的做法很多样,我的做法是找11有一个特点是最上面一位的上左右的没有是很特殊的,以此来判断即可

#include<bits/stdc++.h>

using namespace std;

const int N = 55;
string s[N];

int32_t main() {
    int n , m;
    while( cin >> n >> m ){
        for( int i = 0 ; i < n ; i ++ )
            cin >> s[i];
        int f = 0;
        for( int i = 0 ; i < n && !f ; i ++ )
            for( int j = 0 ; j < m && !f ; j ++ ){
                if( s[i][j] != 'o' || s[i-1][j] == 'o' ) continue;
                if( j > 0 && s[i][j-1] == 'o' ) continue;
                if( j + 1 == m || s[i][j+1] != 'o' ) f = 1 ;
            }
        cout << ( f ? "2018\n" : "2020\n" );
    }
    return 0;
}

G 奇矩阵

首先可以把所有的书全部模二,然后两行的差值的奇偶情况就是两个行异或一下,异或后奇数的个数是奇数个那么和就是奇数。

#include<bits/stdc++.h>

using namespace std;

const int N = 1e3+5;
bitset<N> st[N];

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

int32_t main() {
    int n , m;
    while( cin >> n >> m ){
        for( int i = 1 ; i <= n ; i ++ ) {
            st[i].reset(1);
            for( int j = 1 , x ; j <= m ; j ++ )
                x = read() , st[i][j] = x & 1;
        }
        int f = 1;
        for( int i = 1 ; i <= n && f ; i ++ )
            for( int j = i + 1 ; j <= n && f ; j ++ ){
                if( (st[i] ^ st[j]).count() % 2 == 0 ) f = 0 ;
            }

        cout << ( f ? "Yes\n" : "No\n" );
    }
    return 0;
}

I 共线点

首先把三条直线排序,让最上面的和最下面的连线看能否经过中间的。然后分别找一下两条线最左边的和最右边的两条线,然后如果端点在这两条边之外就是无法相交

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

const int  N = 5;
struct Node{
    int a , b ,y;
    Node( int a , int b , int y ) : a(a) , b(b) , y(y) {};
    Node(){};
} s[N];


int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

int32_t main() {
    while( cin >> s[1].a >> s[1].b >> s[1].y ){
        for( int i = 2 ; i <= 3 ; i ++ )
            cin >> s[i].a >> s[i].b >> s[i].y;
        int h = s[3].y - s[1].y;
        int da = s[3].a - s[1].a;
        int dy = s[2].y - s[1].y;
        int db = s[3].b - s[1].b;
        if( s[1].a * h + da * dy > s[2].b * h ) cout << "No\n";
        else if( s[1].b * h + db * dy < s[2].a * h ) cout << "No\n";
        else cout << "Yes\n";
    }
    return 0;
}

H 矩形并

首先有一个结论从(0,0)(a,b)所有矩形面积之和是\((1+2+3+\cdots+a)\times(1+2+3+\cdots+b)\)这样

设矩形 A的面积是\(S\),那么答案就是\(\frac{a\times(a+1)}{2}\times\frac{b\times(b+1)}{2}+a\times b\times S-V\),其中\(V\)是矩形相交的面积

相交的情况有三种,分别是i<=x2&&j<=y2i<=x2&&j >y2 || i>x2&&j<=y2i>x2&&j>y2

三种情况分类讨论,然后逐个减去,注意容斥就好

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

const int mod = 1e9+7 , inv=500000004;

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

int32_t main() {
    int a , b , x1 , x2 , y1 , y2 , res , s;
    while( cin >> a >> b ){
        cin >> x1 >> x2 >> y1 >> y2;
        s = ( x2 - x1 ) % mod * ( y2 - y1 ) % mod;

        res = ( a * (a+1) % mod * inv % mod ) % mod * ( b * (b+1)  % mod * inv % mod ) % mod + (a * b % mod  * s % mod ) % mod ;
        if( a >= x1 && b >= y1 ){
            a -= x1 , b -= y1 , x2 -= x1 , y2 -= y1;

            int tx = min( a , x2 ) , ty = min( b , y2 );
            res = (res - (tx * (tx+1) % mod * inv % mod * ty % mod * (ty+1) % mod * inv) % mod + mod ) % mod ;
            int tb = b - y2 , ta = a - x2;
            if( tb > 0 ){
                res = ( res - ( tb * tx % mod * (tx+1) % mod * inv % mod * y2 % mod ) + mod )  % mod;
            }
            if( ta > 0 ){
                res = (res - ( ta * ty % mod  * (ty+1) % mod * inv % mod * x2 % mod ) + mod ) % mod;
            }
            if( ta > 0 && tb > 0 ){
                res = ( res - ( ta * tb % mod * s % mod ) + mod ) % mod;
            }
        }
        cout << res % mod << "\n";
    }
}
posted @ 2022-09-12 16:52  PHarr  阅读(47)  评论(0编辑  收藏  举报