前言:

A了四题,第五题差点意思,不过也是上了一点分,感觉这场算是比较简单(应该)?


A.困难数学题

相同的数异或肯定为0了,再来一次也是0

void solve(){
    int n;
    cin>>n;
    cout<<0;
}

B. 构造序列

使用n个正数和m个负数,满足正数不与正数相邻,负数不与负数相邻,问序列最长能构造多长

思路:考虑负数正数相邻,n==m肯定都是可以的,任意一个多一也是可以的,多二就不行了,因为会相邻

void solve(){
    int n,m;
    cin>>n>>m;
    cout<<min(n,m)*2+(n!=m);
}

C.连点成线

感觉和之前的一道线分割点有点像(题目类型上)

思路:直接暴力,点塞数组里面正的排一次算最值,x,y坐标交换再算一次,就可以了

void solve(){
    int n,m;
    cin>>n>>m;
    vector<vector<int> > dp(m+1,vector<int>(2,0));
    for(int i=1;i<=m;i++){
        int x,y;
        cin>>x>>y;
        dp[i][0]=x;
        dp[i][1]=y;
    }
    sort(dp.begin(),dp.end());
    int ans = 0;
    map<LL,LL> q;
    int mx ,mi;
    for(int i=1;i<=m;i++){
       if(!q[dp[i][0]]){
            mi = dp[i][1];
            q[dp[i][0]] = 1;
       }
       else{
            ans = max(ans , dp[i][1]-mi);
       }
    }
    for(int i=1;i<=m;i++){
       swap(dp[i][0],dp[i][1]);
    }
    sort(dp.begin(),dp.end());
     map<LL,LL> qq;
    for(int i=1;i<=m;i++){
       if(!qq[dp[i][0]]){
            mi = dp[i][1];
            qq[dp[i][0]] = 1;
       }
       else{
            ans = max(ans , dp[i][1]-mi);
       }
    }
    cout<<ans;
}

D.我们N个真是太厉害了

an个数看看能否表示出1-n的所有数字

考虑dp,从小到大排序,然后从n开始向下遍历,如果i-x有出现,说明i可以凑出来,这样复杂度大概在on2,考虑到i是从大到小,小的会被重复遍历,考虑在已经遍历过的地方直接结束循环

void solve(){
    int n;
    cin>>n;
    vector<int> a(n,0);
    vector<bool> dp(n + 1, false);
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    sort(a.begin(),a.end());
    dp[0] = true;
    for (int x : a) {
        if(x>n) continue;
        for (int i = n; i >= x; --i) {
            if(dp[i]) break;
            if (dp[i - x]) {
                dp[i] = true;
            }
        }
    } 
    for(int i=1;i<=n;i++){
        if(!dp[i]){
            cout<<i<<endl;
            return;
        }
    }
    cout<<"Cool!"<<endl;
}

E.折返跑

两个杆子是1和n最多可以推n−2次,而且题目要求除了最后一趟每次都推,那不就是要推m−1次 ,所以结果就是C(n-2,m-1)次

直接上组合数模板就行了

#include <bits/stdc++.h>
using namespace std;
using LL = long long;
typedef long long int LL;
const int N = 2e6 + 5;
const int mod = 1e9 + 7;
const int p = 1e9+7;
int64_t fact[N];
int64_t pw(int64_t a, int64_t b) {
    int64_t r = 1;
    while(b > 0) {
        if(b & 1) r = (r * a) % mod;
        b /= 2;
        a = (a * a) % mod; 
    }
    return r;
}
int64_t C(int64_t n, int64_t k) {
    if(n < k) return 0LL;
    return (fact[n] * pw((fact[n - k] * fact[k]) % mod, mod - 2)) % mod;
}
void solve(){
    LL n,k;
    cin>>n>>k;
    cout<<C(n-2,k-1)%p<<endl;
}
int main(){
    int t;
    cin>>t;
    fact[0] = 1;
    for(int64_t i = 1; i < N; ++i) fact[i] = (fact[i - 1] * i) % mod;
    while(t--){
        solve();
    }
}