牛客多校2023 第三场

A

签到,注意0的特判

复制代码
#include <bits/stdc++.h>
using namespace std;
long long x,y;
int main(){
    string s1,s2;
    cin >> s1;
    cin >> s2;
    int Len1 = s1.length();
    int Len2 = s2.length();
    for (int i = 0 ; i < Len1 ; i ++)
        x = 2ll * x + s1[i]-'0';
    for (int i = 0 ; i < Len2 ; i ++)
        y = 2ll * y + s2[i]-'0';
    if (x == 0){
        if (y!=0) cout << "-1";
        else cout << "0";
        return 0;
    }
    cout << abs(x-y);
    return 0;
}
复制代码

B

考虑问题的本质

实际上我们可以对于>n部分和<n部分分开讨论

>n部分来说,其实是需要构成一些下降段,对于<n部分来说,构成一堆上升段

假设划分了k段,则问题转化成把n个数的集合划分成k个组

显然是个第二类斯特林数

我们假设我们枚举了i段,其中有x段上升,y段下降

(x和y差值最大为1)

枚举共选了ab个数

然后就可以用斯特林数算这部分方案了

然后再乘上C(n,a)C(n,b)表示组合数

再乘上x!y!表示任意排列

(2nab)!表示剩下的数随意排列

因为这题失败牌也算,所以要把失败牌的贡献加上,(2n)!

复制代码
#include <bits/stdc++.h>
#define int long long 
using namespace std;
int T;
int N,M;
int fac[706];
int S[505][505];
int C[505][505];
signed main(){
    cin >> T;
    while (T--){
        cin >> N >> M;
        for (int i = 0 ; i <= N+1 ; i ++){
            if ( i == 0 ) S[i][0] = 1; 
            for (int j = 1 ; j <= i ; j ++){
                S[i][j] = (S[i-1][j-1] + S[i-1][j] * j%M)%M;
            }
        }
        for (int i = 1 ; i <= N ; i ++){
            C[i][0] = 1;
            C[i][i] = 1;
            for (int j = 1 ; j < i ; j ++){
                C[i][j] = (C[i-1][j-1] + C[i-1][j])%M;
            }
        }
        fac[0] = 1;
        for (int i = 1 ; i <= 2*N ; i ++){
            fac[i] = fac[i-1] * i %M;
        }
        int ans = fac[2*N]%M;
        for (int i = 0 ; i <=N ; i ++){
            for (int j = 0 ; j <= 1 ; j ++){
                int x,y;
                if ( i == 0 && j == 0) continue; 
                if (j == 0) x = i,y = i;
                else x = i, y = i+1;
                for (int a = x ; a <= N ; a ++)
                    for (int b = y ; b <= N ; b ++){
                        if (a + b < 2*N){
                            ans = (ans + S[a][x] * S[b][y]%M*C[N][a]%M*C[N][b]%M*2ll%M*fac[2*N-a-b]%M*fac[x]%M*fac[y]%M)%M;
                        }
                    }
            }
        }
        cout << ans << endl; 
    }
    return 0;
}
复制代码

D

发现第一列一定全是1或者第一行一定全是0

否则的话如果第一列和第一行都有0且有1的话,一定会有一些数第一列的1小于第一行的0

然后我们就得到了111111...1这样的列,行要都大于等于这个列

所以全1

全0同理

所以题目翻译一下就是把它转成全1/全0列

分类讨论模拟即可

复制代码
#include <bits/stdc++.h>
using namespace std;
string ss[2005];
string ss1[2005];
int main(){
    int N;
    cin >> N;
    for (int i = 1 ; i <= N ; i ++){
        cin >> ss[i];
        ss1[i] = ss[i];
    }
    int cnt = 0;
    int cnt1 = 0;
    int cnt0 = 0;
    for (int i = 1 ; i <= N ; i ++){
        if (ss[i][0] == '1'){
            cnt++;
            for (int j = 0 ; j < N ;j ++){
                if (ss[i][j] == '1'){
                    ss[i][j] = '0';
                }else ss[i][j] = '1';
            }
        }
    }
    cnt0 = 1;
    cnt1 = 0;
    int ans = 1e9+7;
    for (int i = 1 ; i < N ; i ++){
        bool flag = false;
        for (int j = 1 ; j <= N ; j ++){
            if (j!=1 && ss[j][i] != ss[j-1][i]){
                flag = true;
            }
        }
        if (flag){
            cnt =1e9+7;
            break;
        }
        if (ss[1][i] == '1') cnt1 ++;
        else cnt0++;
    }
    if (cnt != 1e9+7){
        int ans1 = min(cnt0,cnt1) + cnt;
        ans = min(ans,ans1);
    }
    cnt = 0;
    for (int i = 1 ; i <= N ; i ++){
        if (ss1[i][0] == '0'){
            cnt ++;
            for (int j = 0 ; j < N ;j ++){
                if (ss1[i][j] == '1'){
                    ss1[i][j] = '0';
                }else ss1[i][j] = '1';
            }
        }
    } 
    cnt1 = 1;
    cnt0 = 0;
    for (int i = 1 ; i < N ; i ++){
        bool flag = false;
        for (int j = 1 ; j <= N ; j ++)
            if (j!=1 && ss1[j][i] != ss1[j-1][i]){
                flag = true;
        }
        if (flag){
            cnt =1e9+7;
            break;
        }
        if (ss1[1][i] == '0') cnt0 ++;
        else cnt1++;
    }
    if (cnt != 1e9+7){
        int ans1 = min(cnt0,cnt1) + cnt;
        ans = min(ans,ans1);
    }
    if (ans == 1e9+7) cout << "-1";
    else cout << ans;
    return 0;
}
复制代码

 

H

根据哥德巴赫猜想,一个大于5的数一定能拆成三个素数和

大力讨论n=1,2,3和>3即可。

复制代码
#include <bits/stdc++.h>
using namespace std;
int N;
long long Sum = 0;
bool IsPrime(long long x){
    if (x == 1) return false;
    for (int i = 2 ; i <= sqrt(x) ; i ++)
        if (x%i == 0) return false;
    return true;
}
int main(){
    cin >> N;
    for (int i = 1 ; i <= N ; i ++){
        long long x;
        cin >> x;
        Sum = Sum + x;
    }
    if (N == 1){
        if (IsPrime(Sum)){
            cout << "Yes";
        }else cout << "No";
        return 0;
    }
    if (N == 2){
        if (Sum < 2){
            cout << "No\n";
            return 0;
        }
        if (Sum%2 ==0){
            if (Sum > 2)
                cout << "Yes\n";
            else cout << "No\n";
            return 0;
        }else
        if (IsPrime(Sum-2)){
            cout << "Yes\n";
            return 0;
        }
        cout << "No\n";
        return 0;
    }
    if (N == 3){
        if (Sum> 5)
            cout << "Yes\n";
        else cout << "No\n";
        return 0; 
    }
    Sum = Sum - 2ll*(N-3);
    if (Sum > 5){
        cout << "Yes\n";
        return 0;
    }
    cout << "No\n";
}
复制代码

J

队友写的,似乎是个toposort?

复制代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;

const int N = 1000010, M = 2000010;

int n, m;
int h[N], e[M], ne[M], idx;
int d[N], q[N];
bool st[N];
int cnt;

void add(int a, int b){
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}

bool topsort()
{
    int hh = 0, tt = -1;

    for(int i = 1; i <= n ; i ++)
        if(!d[i])
            q[++ tt] = i, st[i] = true;

    while(hh <= tt)
    {
        int t = q[hh ++];

        for(int i = h[t] ; i != -1; i = ne[i])
        {
            int j = e[i];
            d[j] --;
            if(d[j] == 0) q[++ tt] = j, st[j] = true;        
        }
    }
    
    cnt = tt;
    return (tt == n - 1);
}

void solve(){
    cin >> n >> m;
    memset(h, -1, sizeof h);

    while(m --){
        int a, b;
        cin >> a >> b;
        add(a, b), d[b] ++;
    }

    bool flag = topsort();

    if(flag){
        cout << 1 << endl;
        for(int i = 0; i < n; i ++)
            cout << q[i] << ' ';
    }
    else{
        cout << 2 << endl;
        for(int i = 1; i <= n; i ++)
            if(!st[i])  
                q[++ cnt] = i;
        
        for(int i = 0; i < n; i ++)
            cout << q[i] << ' ';
        cout << endl;
        for(int i = n - 1; i >= 0; i --)
            cout << q[i] << ' ';
        cout << endl;
    }

}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int T = 1;
    // cin >> T;

    while(T --){
        solve();
    }

    return 0;
}
复制代码

 

posted @   si_nian  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
历史上的今天:
2019-07-24 qzsc游记?
欢迎阅读『牛客多校2023 第三场』
点击右上角即可分享
微信分享提示