The 4th Hangzhou Normal University Freshman

A. 解开束缚缠丝Ⅱ

回文串中至多出现一种字母是奇数个。

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

void solve(){
    int n; cin >> n;
    map<char,int> st;
    int res = 0 , f = 0;
    for( char c ; n ; n -- )
        cin >> c , st[c] ++;
    for( auto [k , v] : st ){
        res += v;
        if( v % 2 == 1 ) f = 1 , res --;
    }
    cout << res + f << "\n";
}

int32_t main() {
    ios::sync_with_stdio(false) , cin.tie(nullptr) , cout.tie(nullptr);
    int t ; cin >> t;
    while( t -- ) solve();
    return 0;
}

B. 7 的意志

计算前缀和,枚举左端点,二分右端点,复杂度\(O(n\log n)\)

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

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

void solve(){
    int n = read();
    vector<int> a(n+1);
    for( int i = 1 ; i <= n ; i ++ ) a[i] = read() + a[i-1];
    auto search = [a,n]( int st ){
        int l = st , r = n , ans = n , mid ;
        while(l <= r){
            mid = (l + r) >> 1;
            if( a[mid] - a[st-1] >= 7777 ) ans = mid , r = mid - 1;
            else l = mid + 1;
        }
        return ans;
    };
    int res = 0;
    for( int i = 1 , j ; i <= n ; i ++ ){
        j = search(i);
        res += ( a[j] - a[i-1] == 7777 );
    }
    printf("%d\n" , res);
}

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

C. 迷宫的十字路口

数量不多直接模拟就好。

用结构体存储每一次操作后的状态。结构题中包含位置,获得物品数量,轴上物品的位置。

操作1,就是移动,暴力统计移动过程中能拿哪些物品即可。

操作2,对轴上所有的点取相反数即可

操作3,交换x,y轴就好

操作4,回到\(T-1\)次操作后的状态即可

注意,即使位置没有移动也可能会获得物品

#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 state {
    int x, y, sum;
    vector<int> X, Y;

    state(const vector<pair<int, int>> &s) {
        x = y = sum = 0;
        for (auto [r, c]: s) {
            if (r == 0) Y.push_back(c);
            if (c == 0) X.push_back(r);
        }
        sort(X.begin(), X.end()), sort(Y.begin(), Y.end());
    }

    void op1(char op, int t) {

        if ((op == 'X' && (x + t) * y != 0) || (op == 'Y' && x * (y + t) != 0)) return x = y = 0, void();
        if (op == 'X') {
            vector<int> cur;
            int l = min(x, x + t), r = max(x, x + t);
            for (auto i: X)
                if (i >= l && i <= r) cur.push_back(i);
            for (auto i: cur)
                X.erase(lower_bound(X.begin(), X.end(), i));
            sum += cur.size(), x += t;
        } else {
            vector<int> cur;
            int l = min(y, y + t), r = max(y, y + t);
            for (auto i: Y) if (i >= l && i <= r) cur.push_back(i);
            for (auto i: cur)
                Y.erase(lower_bound(Y.begin(), Y.end(), i));
            sum += cur.size(), y += t;
        }
        return;
    }

    void op2(char op) {
        if (op == 'X') {
            for (auto &i: X) i = -i;
            sort(X.begin(), X.end());
        } else {
            for (auto &i: Y) i = -i;
            sort(Y.begin(), Y.end());
        }
        op1('X', 0), op1('Y', 0);
        return;
    }

    void op3() {
        swap(X, Y);
        op1('X', 0), op1('Y', 0);
        return;
    }
};


int32_t main() {
    int n = read();
    vector<pair<int, int>> a(n);
    for (auto &[x, y]: a) x = read(), y = read();
    state now(a);
    vector<state> T;
    T.push_back(now);
    char s[2];
    for (int i = 1, m = read(), op, t; i <= m; i++) {
        op = read();
        if (op == 1) {
            scanf("%s", s), t = read();
            now.op1(s[0], t);
        } else if (op == 2) {
            scanf("%s", s);
            now.op2(s[0]);
        } else if (op == 3) {
            now.op3();
        } else if (op == 4) {
            t = read();
            if (t != i) now = T[t - 1];
        }
        T.push_back(now);
    }
    cout << now.sum << "\n";
    return 0;
}

D. 转动命运之轮

要构造转动\(c\)轮的序列\(w_i\),即如果把传递当成是一个有向图的话,则图中最大的环的大小就是\(c\)

可以枚举每个人\(k\)所在环的大小\(c_k\),如果环的大小是\(i\),则还要从剩下\(n-1\)个人中选出\(i-1\)个,有\(C_{n-1}^{k-1}\)中情况,环上的排序情况是\((i-1)!\),环外的排序情况是\((n-i)!\),所以\(k\)所产生的贡献就是\(h_k\times \sum_{i=1}^n C_{n-1}^{k-1} (n-i)!(i-1)!\),所以整体的答案就是

\[\sum_{k=1}^{n} [ h_k\times \sum_{i=1}^n C_{n-1}^{k-1} (n-i)!(i-1)!]=\sum_{k=1}^{n} h_k\times \sum_{i=1}^n C_{n-1}^{k-1} (n-i)!(i-1)! \]

#include <bits/stdc++.h>

using namespace std;

#define int long long
const int N = 2005, mod = 998244353;
int fact[N], invFact[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;
}

int power(int x, int y) {
    int ans = 1;
    x = x % mod;
    while (y) {
        if (y & 1) ans = ans * x % mod;
        y >>= 1, x = x * x % mod;
    }
    return ans;
}

int inv(int x) {
    return power(x, mod - 2);
}

int C(int x, int y) { // x 中选 y 个
    return fact[x] * invFact[x - y] % mod * invFact[y] % mod;
}

void init() {
    fact[0] = 1, invFact[0] = inv(1);
    for (int i = 1; i < N; i++)
        fact[i] = fact[i - 1] * i % mod, invFact[i] = inv(fact[i]);
}

int32_t main() {
    init();
    int n = read(), res = 0;
    for (int i = 1, x; i <= n; i++)
        x = read(), res = (res + x) % mod;
    int ans = 0;
    for (int i = 1, t; i <= n; i++) {
        t = C(n - 1, i - 1) * fact[i] % mod * fact[n - i] % mod;
        ans = (ans + t) % mod;
    }
    cout << res * ans % mod;
    return 0;
}

赛后发现了Note中的最后一句话

在本题中,可以理解为对所有满足 \(P\in U_n\)的集合 \(P\) 进行求和。

所以当\(c_k\)确定时有\((n-1)!\)中情况,所以对于\(k\)的答案是\(h_k\sum_{i=1}^{n}i(n-1)!=h_k\frac{n(1+n)}{2}(n-1)!=\frac{1}{2}h_k(n+1)!\)

漏掉提示真尴尬。。。

#include <bits/stdc++.h>

using namespace std;

#define int long long
const int N = 2005, mod = 998244353;
int fact[N], invFact[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 = read() , ans = 0 , res = 1;
    for( int i = 1 ; i <= n ; i ++ )
        ans = ( ans + read() ) % mod ;
    for( int i = 3 ; i <= n+1 ; i ++ )
        res = ( res * i ) % mod;
    cout << ans * res % mod;
    return 0;
}

E. 计算最小值

显然差值之和最小,最简单的方法是按照大小顺序取,例如\(\{1,2,3,4,5\}=|2-1|+|3-2|+|4-3|+|5-4|=5-1\),所以就是区间中的\(\max-\min\),这里要注意的是区间内必须包含\(n\)种,所以把所有的数字放在一起,同时记录属于哪一种,按照大小排序,最后用双指针算法做一下就好

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

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



int32_t main() {
    int n = read() , m = read();
    vector< pair<int,int> > v;
    vector<int> cnt(n+1);
    for( int i = 1 ; i <= n ; i ++ )
        for( int j = m , x ; j ; j -- )
            x = read() , v.emplace_back( x , i );
    sort( v.begin(), v.end());
    int res = INT_MAX;
    for( int l = 0 , r = -1 ; l < v.size() ; l ++ ){
        while( r+1 < v.size() && cnt[0] != n ){
            r ++ , cnt[ v[r].second ] ++;
            if( cnt[ v[r].second ] == 1 ) cnt[0]++;
        }
        if( cnt[0] != n ) break;
        if( v[l].second != v[r].second ) res = min( res , v[r].first - v[l].first );
        cnt[ v[l].second ]--;
        if( cnt[v[l].second] == 0 ) cnt[0] --;
    }
    cout << res << "\n";
    return 0;
}

F. 月光奏鸣曲

模拟题,预处理选旋转90,180,270度的情况,旋转270就是反方向旋转90,然后按照题目要求比较就好。推荐用vector因为可以直接用==比较

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

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

void f( const int & n , const vector<vector<int>> & a , vector<vector<int>> & b ){
    for( int i = 0 ; i < n ; i ++ )
        for( int j = 0 , l = n-1 ; j < n ; j ++ , l -- )
            b[i][j] = a[l][i];
    return;
}


void solve(){
    int n = read();
    vector< vector<int> > a( n , vector<int>(n));
    auto b = a , c = a , d = a , e = a;
    for( auto &it : a )
        for( auto &i : it ) i = read();
    for( auto &it : b )
        for( auto &i : it ) i = read();
    f(n, a, c), f(n, c, d) , f(n, d, e);
    
    if( a == b ) printf("0\n");
    else if( c == b || e == b ) printf("1\n");
    else if( d == b ) printf("2\n");
    else printf("-1\n");
    return;
}

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

G. 电子表校对

模拟题,先处理出所有数字的表示方式,然后转换两个时间,先把时间都转换成秒,然后再比较

#include <bits/stdc++.h>

using namespace std;


#define int long long


typedef array<string, 3> num;

const num s[10] = {
        {" _ ", "| |", "|_|",},
        {"   ", "  |", "  |",},
        {" _ ", " _|", "|_ ",},
        {" _ ", " _|", " _|",},
        {"   ", "|_|", "  |",},
        {" _ ", "|_ ", " _|",},
        {" _ ", "|_ ", "|_|",},
        {" _ ", "  |", "  |",},
        {" _ ", "|_|", "|_|",},
        {" _ ", "|_|", " _|",},};

num x[6];
int tx[6];

void print(num t) {
    for (auto i: t)
        cout << i << "\n";
}

string str;
int hh, mm, ss;

int32_t main() {
    for (int j = 0; j < 3; j++) {
        getline(cin, str);
        for (int i = 0, l = 0; i < 18; i += 3, l++)
            x[l][j] = str.substr(i, 3);
    }
    for (int i = 0; i < 6; i++)
        for (int j = 0; j < 10; j++)
            if (x[i] == s[j]) tx[i] = j;
    hh = tx[0] * 10 + tx[1], mm = tx[2] * 10 + tx[3], ss = tx[4] * 10 + tx[5];
    int a = hh * 60 * 60 + mm * 60 + ss;
    for (int j = 0; j < 3; j++) {
        getline(cin, str);
        for (int i = 0, l = 0; i < 18; i += 3, l++)
            x[l][j] = str.substr(i, 3);
    }
    for (int i = 0; i < 6; i++)
        for (int j = 0; j < 10; j++)
            if (x[i] == s[j]) tx[i] = j;
    hh = tx[0] * 10 + tx[1], mm = tx[2] * 10 + tx[3], ss = tx[4] * 10 + tx[5];
    int b = hh * 60 * 60 + mm * 60 + ss;
    int c = abs(a - b);
    ss = c % 60, mm = c / 60, hh = mm / 60, mm %= 60;
    tx[0] = hh / 10, tx[1] = hh % 10, tx[2] = mm / 10, tx[3] = mm % 10, tx[4] = ss / 10, tx[5] = ss % 10;
    for( int i = 0 ; i < 6 ; i ++ )
        x[i] = s[tx[i]];
    if( a < b ) cout << "late\n";
    else if( a > b ) cout << "early\n";
    else cout << "gang gang hao\n";
    for( int j = 0 ; j < 3 ; j ++ ){
        for( int i = 0 ; i < 6 ; i ++ ) cout << x[i][j];
        cout << "\n";
    }
    return 0;
}

H. 简单的 LRU 问题

模拟题,用一下语法糖快速的转换进制会简单一些,但是注意不能有行末空格,我因为这个WA2次

#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() {

    auto to_num = [](int x, int y) {
        ostringstream ss;
        string num;
        ss << "0x" << setfill('0') << setw(y) << hex << x;
        return ss.str();
    };

    int n = read(), m = read();
    string line = "+------+";
    char tab = '|';
    for (int i = 1; i <= n; i++) line += "--------+";
    line += "\n";

    // title
    cout << line;
    cout << "|      |";
    for (int i = 0; i < n; i++)
        cout << "  "<< to_num(i, 2) << "  |";
    cout << "\n" << line;

    vector<pair<int, int> > ram;
    for (int i = 0, x, f; i < m; i++) {
        cout << "| " << to_num(i, 2) << " |";
        x = read(), f = 0;
        for (auto &[k, v]: ram)
            if (v == x) k = i, f = 1;
        if (f == 0 && ram.size() < n) ram.emplace_back(i, x), f = 1;
        if (f == 0) {
            sort(ram.begin(), ram.end());
            ram[0].first = i, ram[0].second = x;
            f = 1;
        }
        sort(ram.begin(), ram.end());
        for (auto [k, v]: ram) {
            cout << " " << to_num(v, 4) << " |";
        }
        for (int i = ram.size() + 1; i <= n; i++)
            cout << "        |";
        cout << "\n" << line;
    }
    return 0;
}

I. 好想听肆宝唱歌啊

排序,读入可以整行读入,也可以一个单词一个单词读入

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


void solve(){
    
    string s , ch = "  ";
    vector<pair<int,string>> a;
    
    while( true ){
        cin >> s;
        if( s.back() == '.' || s.back() == '!' || s.back() == '?' ){
            ch[1] = s.back();
            a.emplace_back( 0 , s.substr( 0 , s.size()-1) );
            break;
        }else a.emplace_back( 0 , s );
    }
    int n = a.size();

    for( int i = 0 , j = 1 ; j <= n ; j += 2 , i ++ ) a[i].first = j;
    for( int i = n-1 , j = 2 ; j <= n ; j += 2 , i -- ) a[i].first = j;

    sort(a.begin(), a.end());
    for( auto [ k , v ] : a )
        cout << v << ( ch[k==n] );
    cout << "\n";
    return;
}

int32_t main() {
    ios::sync_with_stdio(false) , cin.tie(nullptr) , cout.tie(nullptr);
    int n; cin >> n;
    vector< pair<int,string> > v(n);
    for(auto &[ w , s ] : v) cin >> w >> s;
    sort( v.begin() , v.end() , greater<pair<int,string>>() );
    int k ; cin >> k;
    cout << v[k].second;
    return 0;
}

J. 毁灭凤凰人

胜利条件两种

  1. 有一张ATK大于毁灭凤凰人的0牌和一张1牌
  2. 有一张2牌和一张任意牌

注意大于等于2500或大于2100

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

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


int s[2] = {2500,2101};

int32_t main() {
    int n = read() , m = read();
    m = s[m];
    int a = 0 , b = 0 , c = 0;
    for( int x , i = 1 ; i <= n ; i ++ ){
        x = read();
        if( x == 0 ) a = max( a , read() );
        else if( x == 1 ) b ++;
        else c ++;
    }
    if( n > 1 && c > 0 ) printf("haoye\n");
    else if( a >= m && b > 0 ) printf("haoye\n");
    else printf("QAQ\n");
    return 0;
}

K. 欢迎来到杭师大

注意换行

#include<bits/stdc++.h>

using namespace std;

int main(){
	int n;
	cin >> n;
	for( ; n ; n -- )
		cout <<"Welcome to HZNU\n";
}

L. Ayanoto 变形记

除非x=0,否则nx一定可以到达

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

void solve(){
    int n , x;
    cin >> n >> x;
    if( x ) cout << "yes\n";
    else cout << "no\n";
}

int32_t main() {
    ios::sync_with_stdio(false) , cin.tie(nullptr) , cout.tie(nullptr);
    int t ; cin >> t;
    while( t -- ) solve();
    return 0;
}

M. P 龙学长的教诲

重新编一下号就行

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

void solve(){
    
    string s , ch = "  ";
    vector<pair<int,string>> a;
    
    while( true ){
        cin >> s;
        if( s.back() == '.' || s.back() == '!' || s.back() == '?' ){
            ch[1] = s.back();
            a.emplace_back( 0 , s.substr( 0 , s.size()-1) );
            break;
        }else a.emplace_back( 0 , s );
    }
    int n = a.size();

    for( int i = 0 , j = 1 ; j <= n ; j += 2 , i ++ ) a[i].first = j;
    for( int i = n-1 , j = 2 ; j <= n ; j += 2 , i -- ) a[i].first = j;

    sort(a.begin(), a.end());
    for( auto [ k , v ] : a )
        cout << v << ( ch[k==n] );
    cout << "\n";
    return;
}

int32_t main() {
    ios::sync_with_stdio(false) , cin.tie(nullptr) , cout.tie(nullptr);
    int t ; cin >> t;
    while( t -- ) solve();
    return 0;
}
posted @ 2023-02-17 23:31  PHarr  阅读(103)  评论(0编辑  收藏  举报