2024.07.27科大訊飛(有困難題)

失控D大白兔發表於2024-09-03

1. 購房之旅

小強有n個朋友,每個朋友有一定數量的金幣,現在他們要購買房子,一共有m個房子,每個房子有兩個引數:舒適度和價格,當一個人的金幣大於等於一個房子的價格時,才可以購買房子,且要滿足以下條件:1.一個人至多購買一個房子。2.一個房子至多被一個人購買。現在小強想知道n個朋友購買的房子的舒適度之和最大可能是多少?

排序再使用紅黑樹貪心(map或者mutiset)
int main(){
    int n; int m;
    cin>>n;
    cin>>m;
    vector<int> coin(n);
    map<int,int> mp;
    //記錄每個人的錢
    for(int i=0;i<n;i++){
        cin>>coin[i];
        mp[coin[i]]++;
    }
    //記錄房子舒適度和對應價格
    vector<vector<int>> house(m,vector<int>(2,0));
    for(int i=0;i<m;i++){
        cin>>house[i][0];
        cin>>house[i][1];
    }
    //儘量使得舒適度最大,對舒適度進行排序,然後順序遍歷房子,同時選擇大於房子價格且最接近的金錢去購買
    sort(house.begin(),house.end(),[&](auto a,auto b){
        if(a[0]==b[0]) return a[1]<b[1];//相同舒適度,價格便宜放前面
        return a[0]>b[0];//舒適度高的放前面
    });
    int res = 0;
    for(int i=0;i<m;i++){
        auto it = mp.lower_bound(house[i][1]);
        if(it!=mp.end()){
            res += house[i][0];
            mp[it->first]--;
            if(mp[it->first]==0)
                mp.erase(it->first);
        }
    }
    cout<<res;
    
    return 0;
}

2. base

我們想知道給定一個 10 進位制數 n ,其在 2 ~36 進位制下的所有進製表示中,含有 1的數量最多是多少。

進行轉換計數
int compute(int n,int base){//計算在指定進位制下1的個數
    int res = 0;
    while(n){
        if(n%base==1) res++;
        n/=base;
    }
    return res;
}

int main(){
    int n;
    cin>>n;
    int mx = 0;
    for(int i=2;i<=36;i++)
        mx = max(mx,compute(n,i));
    cout<<mx;
    return 0;
}

3. 異或和

給定兩個整數 n和 m ,詢問滿足如下條件的序列 a 的數量:
序列a的長度為n;
序列a的值均大於等於0且小於等於m;
序列a是一個非遞減序列;
序列a所有元素的異或值為m。

  • 首先考慮動態規劃,因為結果數量很大
  • dp[i][j][k]表示考慮前i個數字,最後一個數字j,異或和為k的方案數。
  • 結果為dp[n][m][i]的累加和
  • f[i][j][k] += f[i-1][l][k^l] 為轉移方程,為了保證遞增,j需要大於等於l
  • 字首和最佳化
int main() {
    int n, m;
    cin >> n >> m;

    // f[i][k][l]表示前i個數字,異或和為k,以l為結尾的方案數
    vector<vector<vector<ll>>> f(n + 1, vector<vector<ll>>(2 * m + 1, vector<ll>(m + 1, 0)));
    f[0][0][0] = 1;//初始狀態

    for (int i = 1; i <= n; ++i) {//遍歷n個數作為上限
        // 字首和陣列
        vector<vector<ll>> pre(2 * m + 1, vector<ll>(m + 1, 0));
        for (int t = 0; t <= 2 * m; ++t) {
            for (int p = 0; p <= m; ++p) {
                pre[t][p] = f[i - 1][t][p];
                if (p != 0) pre[t][p] = (pre[t][p] + pre[t][p - 1]) % MOD;
            }
        }

        for (int k = 0; k <= 2 * m; ++k) {
            for (int l = 0;l <= m && (k ^ l) <= 2 * m; ++l) {
                f[i][k][l] = (f[i][k][l] + pre[k ^ l][l]) % MOD;
            }
        }
    }

    ll ans = 0;
    for (int i = 0; i <= m; ++i) {
        ans = (ans + f[n][m][i]) % MOD;
    }

    cout << ans << endl;
    return 0;
}

相關文章