2020 年第一届辽宁省大学生程序设计竞赛

I 鸽子的整数运算

#include<bits/stdc++.h>

using namespace std;

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() {
    for( int T = read() , op , a , b ; T ; T -- ){
        op = read() , a = read() , b = read();
        if( op == 1 ) cout << a + b << "\n";
        else if( op == 2 ) cout << a - b << "\n";
        else if( op == 3 ) cout << a * b << "\n";
        else cout << a / b << "\n";
    }
    return 0;
}

G 管管的幸运数字

首先用线性筛筛出所有的素数,如果不是素数找到最接近的素数

#include<bits/stdc++.h>

using namespace std;

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;
}
const int N = 20005;
vector<int> prime;
bitset<N> not_prime;

int32_t main() {
    for( int i = 2 ; i <= 20000 ; i ++ ){
        if( not_prime[i] == 0 ) prime.push_back(i);
        for(auto it : prime  ){
            if( it * i > 20000 ) break;
            not_prime[ it * i ] = 1;
            if( i % it == 0 ) break;
        }
    }
    for( int T = read() , x ; T ; T -- ){
        x = read();
        if( not_prime[x] ){
            int res = INT_MAX;
            for( auto it : prime )
                res = min( res , abs( x - it) );
            cout << res << "\n";
        } else{
            cout << "YES\n";
        }
    }
    return 0;
}

A 组队分配

每次读入的时候直接计算出每个人是哪一队的第几名就好了

#include<bits/stdc++.h>

using namespace std;

const int N = 4e4+5;
pair< int , string > ve[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;
}

string a[N][5];

void solve() {
    int n = read();
    string s;
    for (int i = 1, x; i <= (n * 3) ; i++) {
        cin >> s >> x;
        a[(x - 1) / 3][x % 3] = s;
    }
    for (int i = 0; i < n; i++){
        cout << "ACM-"<<i<<" ";
        cout << a[i][0] << " " << a[i][2] << " " << a[i][1] <<"\n";
    }
}

int32_t main() {
    for( int T = read() ; T ; T -- )
        solve();
    return 0;
}

B 两点距离

如果两点位置重合,距离为0。如果两点的距离互素,距离为1。其他情况下距离统统是二,可以先跳到一个质数,然后再从质数跳到第二个数。

#include<bits/stdc++.h>

using namespace std;

const int N = 4e4+5;
pair< int , string > ve[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;
}

string a[N][5];

int32_t main() {
    int n = read() , q = read();
    for( int l , r ; q ; q -- ){
        l = read() , r = read();
        if( l == r ) cout << "0\n";
        else if( __gcd( l , r ) == 1 ) cout << "1\n";
        else cout << "2\n";
    }
    return 0;
}

C 轮到谁了?

i个月有f[i]对兔子,显然f[i]就是斐波那契数列,然后标号是从0开始,所以最后一对兔子就是(f[n]-1)%m

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

const int N = 1005;

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;
}

int f[N];

void solve(){
    f[0] = 0 , f[1] = 1;
    int n = read() , m = read();
    for( int i = 2 ; i <= n ; i ++)
        f[i] = (f[i-1] + f[i-2]) % m;
    cout << (f[n]-1 + m ) % m << "\n";
    return;
}


int32_t main() {
    for( int T = read() ; T ; T -- )
        solve();
    return 0;
}

F 最长回文串

把所有的字符串排序,然后统计一下每种字符串有多少个,从中取出偶数个。对于剩下的串至多取一个,判断剩下的中有没有可以构成回文串的。

判断构成回文串就是统计字符串中字母的个数,奇数个的字母种类数不超过一就可以构成回文串。

#include<bits/stdc++.h>

using namespace std;

int n , m , res , f;
map< string , int > st;

int32_t main() {
    cin >> n >> m;
    for( string s ; n ; n -- ){
        cin >> s;
        sort( s.begin() , s.end() );
        st[s]++;
    }
    for( auto [k,v] : st ){
        res += v - (v&1);
        if( v&1 && !f ){
            array < int , 26 > t{};
            for( auto it : k ) t[it-'a'] ++;
            int cnt = 0;
            for( auto it : t )
                cnt += it & 1;
            if( cnt <= 1 ) f = 1;
        }
    }
    cout << ( res + f ) * m << "\n";

    return 0;
}

J 鸽者文明的三体问题

因为三角形的数量很少,每次暴力的枚举三角形然后判断点是否在三角形内就好了。

判断点是否在三角形中的方法可以三角形的面积和三个小三角形的面积之和是否相同来判断。但是这种方法有浮点数运算的误差所以无法得到正确的结果。另一种方法是用向量的外积来分别判断点在每一条线的左侧还是右侧。

#include<bits/stdc++.h>

using namespace std;

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;
}

struct Triangle{
    int ax , ay , bx , by , cx ,cy;
    Triangle(){};
    Triangle( int ax , int ay , int bx , int by , int cx , int cy ) : ax(ax) , ay(ay) , bx(bx) , by(by) , cx(cx) , cy(cy) {};
};

vector<Triangle> t;

pair<int,int> getVector( int x , int y , int a , int b ){
    return pair{ x - a , y - b };
}

bool product( pair<int,int> a , pair<int,int> b ){
    return ( a.first * b.second - a.second * b.first ) > 0;
}

int32_t main() {
    int n = read() , q = read();
    for( int i = 1 , ax , ay , bx , by , cx , cy ; i <= n ; i ++ )
        ax = read() , ay = read() , bx = read() , by = read() , cx = read() , cy = read(),
        t.push_back({ax,ay,bx,by,cx,cy});
    for( int x , y , cnt ; q ; q -- ){
        x = read() , y = read() , cnt = 0;
        for( auto [ax,ay,bx,by,cx,cy] : t ){
            pair<int,int> ao = getVector( x , y , ax , ay );
            pair<int,int> bo = getVector( x , y , bx , by );
            pair<int,int> co = getVector( x , y , cx , cy );
            pair<int,int> ab = getVector( bx , by , ax , ay );
            pair<int,int> bc = getVector( cx , cy , bx , by );
            pair<int,int> ca = getVector( ax , ay , cx , cy );
            bool f1 = product( ao , ab ) , f2 = product( bo , bc ) , f3 = product( co , ca );
            cnt += ( f1 == f2 && f2 == f3 );
        }
        if( cnt & 1 ) cout << "Yes\n";
        else cout << "No\n";
    }
    return 0;
}

K Xor

Xor[i]表示当前i个数的前缀异或和。f[t]表示从1i中,所有前缀异或和为t的位置和合法区间划分方案数。

考虑前i个数和合法划分中,最后一个区间的异或和一定是x,所以从第一个区间到倒数第二个区间的前缀异或和一定是XOr[i] ^ x,所以转移方程就是f[Xor] += f[ Xor ^ x ]

答案就是f[ Xor[n] ^ x]

#include<bits/stdc++.h>

using namespace std;

const int mod = 1e9+7;
unordered_map<int,int> f;

int read() {...}

int32_t main() {
    int n = read() , m = read() , res = 0 , Xor = 0;
    f[0] = 1;
    for( int i = 1 , x ; i <= n ; i ++ ){
        x = read() , Xor ^= x;
        f[Xor] = ( f[Xor] + f[Xor^m] ) % mod;
    }
    cout << f[Xor^m] << "\n";
    return 0;
}
posted @ 2022-08-17 20:04  PHarr  阅读(83)  评论(0编辑  收藏  举报