2024.07.27科大讯飞(有困难题)

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^j] 为转移方程,为了保证递增,l需要小于j,这里使用四个变量也就是四重循环
  • 前缀和优化,优化不同结尾的累加和
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;
}
posted @ 2024-09-03 17:57  失控D大白兔  阅读(193)  评论(0编辑  收藏  举报