【牛客训练记录】"华为杯"2024年广东工业大学新生赛(同步赛)

训练情况

赛后反思

组合数学还得加练,J题奇妙的乘法逆元预处理,开个unordered_map记忆化就过了?!,E题太头铁了,异或不算就直接交,F题又是急到没取模就直接交。

A题

字符串 Tomori 后面补上 Haruhikage

#include <bits/stdc++.h>
// #define int long long
#define endl '\n'

using namespace std;

void solve(){
    string s; cin>>s;
    cout<<s<<endl;
    if(s == "Tomori") cout<<"Haruhikage"<<endl;
}

signed main(){
    int T; cin>>T; while(T--)
    solve();
    return 0;
}

N题

找票数最多的人的名字

#include <bits/stdc++.h>
// #define int long long
#define endl '\n'

using namespace std;

string ans;
int now;

void solve(){
    string s; cin>>s;
    int x; cin>>x;
    if(x > now){
        now = x;
        ans = s;
    }
}

signed main(){
    int T; cin>>T; while(T--)
    solve();
    cout<<ans<<endl;
    return 0;
}

F题

由于这题保证字符串之间互不相同,所以它下面给的字符串并没有什么用,所以只需要 \(n\) 就可以计算答案,对于某一种缩写,对答案的贡献就是它的全排列,就是从 \(n\) 个字符串里面选 \(1,2,3,4,\cdots,n\) 的全排列,所以这题的答案是 \(A_n^1 + A_n^2 + A_n^3 \cdots A_n^n\)

#include <bits/stdc++.h>
#define int long long
#define endl '\n'

using namespace std;

const int mod = 1e9 + 7;

void solve(){
    int n; cin>>n;
    int ans = 0;
    int now = 1;
    for(int i = n;i;i--){
        now *= i;
        now %= mod;
        ans += now;
        ans %= mod;
    }
    cout<<ans<<endl;
}

signed main(){
    // int T; cin>>T; while(T--)
    solve();
    return 0;
}

I题

\(i\) 可以跳到 \(a_i\),对于两个不互通的环,我们需要交换两个环上的任意元素即可打通,所以最后需要交换的次数就是不同环的个数-1,所以我们直接并查集(DSU)维护,最后求有多少个不同的环,答案再减一。

#include <bits/stdc++.h>
// #define int long long
#define endl '\n'

using namespace std;

const int N = 1e5 + 3;

int fa[N];

int Find(int x){
    if(fa[x] == x) return x;
    return fa[x] = Find(fa[x]);
}

void Union(int x,int y){
    x = Find(x); y = Find(y);
    if(x == y) return;
    fa[y] = x;
}

void solve(){
    int n; cin>>n;
    vector<int> a(n + 1);
    for(int i = 1;i<=n;i++) fa[i] = i,cin>>a[i];
    for(int i = 1;i<=n;i++){
        Union(i,a[i]);
    }
    vector<bool> vis(n + 1);
    int ans = 0;
    for(int i = 1;i<=n;i++){
        if(!vis[Find(i)]){
            vis[Find(i)] = 1;
            ans++;
        }
    }
    cout<<ans-1<<endl;
}

signed main(){
    int T; cin>>T; while(T--)
    solve();
    return 0;
}

E题

我们观察发现每一行每一列上的元素都互不相同才能让异或最小

#include <bits/stdc++.h>
// #define int long long
#define endl '\n'

using namespace std;

const int N = 507;

int n;
int a[N][N];

void solve(){
    cin>>n;
    for(int i = 0;i<n;i++){
        for(int j = 0;j<n;j++){
            a[i][j] = (i+j)%n;
        }
    }
    int ans = 0;
    for(int i = 0;i<n;i++) ans^=(i+1);
    cout<<ans<<endl;
    for(int i = 0;i<n;i++){
        for(int j = 0;j<n;j++){
            cout<<a[i][j]+1<<" ";
        }
        cout<<endl;
    }
}

signed main(){
    // int T; cin>>T; while(T--)
    solve();
    return 0;
}

J题

\(n\) 次,输 \(n-1\) 次,输的位置可以在任意位置,有 \(C_{n+k-1}^k\) 种,由于是独立事件,概率就是每个事件概率的乘积,所以答案就是

\[\sum_{i=0}^{n-1}p^n \times (1-p)^i \times C_{n+k-1}^k \]

#include <bits/stdc++.h>
#define int long long
#define endl '\n'

using namespace std;

const int mod = 1e9 + 7;
const int N = 2e5 + 3;

int jc[N];

inline int read(){
    int s = 0; char c = getchar();
    while(!isdigit(c)) c = getchar();
    while(isdigit(c)){
        s = (s << 1) + (s << 3) + (c ^ 48);
        c = getchar();
    }
    return s;
}

void print(int x){
    if(x > 9) print(x/10);
    putchar(x%10+48);
}

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

unordered_map<int,int> pinv;

int inv(int x){
    if(pinv[x]) return pinv[x];
    return pinv[x] = ksm(x,mod-2);
}

void pre(){
    jc[0] = 1;
    for(int i = 1;i<=N-3;i++) jc[i] = jc[i-1]*i,jc[i] %= mod;
}

int C(int n,int m){
    return (((jc[n]*inv(jc[n-m])) % mod)*inv(jc[m])) % mod;
}

void solve(){
    int n,p,q; n = read(); p = read(); q = read();
    int win = (p*inv(q)) % mod;
    int lose = ((q-p)*inv(q)) % mod;
    int powwin = ksm(win,n);
    int powlose = 1;
    int ans = 0;
    for(int k = 0;k<=n-1;k++){
        ans += (((powwin*powlose) % mod)*C(n+k-1,k)) % mod;
        powlose *= lose; powlose%=mod;
        ans %= mod;
    }
    print(ans); puts("");
}

signed main(){
    pre();
    int T; T = read(); while(T--)
    solve();
    return 0;
} 
posted @ 2024-12-01 18:30  MNNUACM_2024ZY  阅读(139)  评论(0)    收藏  举报