牛客周赛 Round 39

比赛链接

题解

1、小红不想做鸽巢原理

思路:贪心问题(个人理解,不知道怎么应用鸽巢原理)

1、应为每次可以取k个,所以最后每个颜色色剩余 a[i]%k 个小球, 总的剩余球数为sum

2、这是后我们想让剩余的颜色种类数尽量的少,并且剩余小球的个数为sum个,这时候我们想到,

让剩余颜色中,小球个数最多的剩余,这样就会让剩余的颜色种类最少。

#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
typedef long long LL;
int a[N];
LL sum;
int main()
{
    int n; cin>>n;
    LL k; cin>>k;
    for(int i = 0; i<n; i++)
    {
        scanf("%d",&a[i]);
        a[i] %= k;
        sum += a[i];
    }
    sum %= k;//最后剩余的小球个数
    sort(a,a+n);
    int cnt = 0,res = 0;
    for(int i = n-1; i>=0; i--)
    {
  
        if(cnt>=sum)//当我们想让剩余小球的个数,超过实际剩余个数的时候,就结束
        {
            cout<<res<<endl;
            break;
        }
        else
        {
            cnt += a[i];
            res++;//颜色种数增加
        }
    }
    return 0;
}

2、小红不想做完全背包(easy)

#include<bits/stdc++.h>
using namespace std;
const int N = 2010;
typedef long long LL;
int a[N];
map<int,int> mp;
int main()
{
    int n,p;
    cin>>n>>p;
    for(int i = 0; i<n; i++)
    {
        cin>>a[i];
        a[i]%=3;
        mp[a[i]] = 1;
    }
    if(mp[0])
    {
        cout<<1<<endl;
    }
    else if(mp[1] && mp[2])
    {
        cout<<2<<endl;
    }
    else
    {
        cout<<3<<endl;
    }
    return 0;
}

3、小红不想做完全背包 (hard)

思路:

1、dp问题,我们用f[i]表示,选取的物品价值之和模p为i的集合,f[i] 的值为最少的物品数量

2、我们想一想如何转移,有两种方法:一种是根据当前的状态,转移下一种状态 ;另一种是根据上一种状
态转移出来现在的状态;

3、初始化问题,x = a[i]%p, f[x] 最少肯定是一件,其余的初始化为正无穷。

4、两种转移方法:

f[j] = min(f[j], f[(j-a[i]+p % p)]+1);

int ne = (a[i]+j)%p; f[ne] = min(f[ne], f[j] + 1);

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
const int N = 2005;
const long long INF = 1e18;
int a[N];
long long f[N];
int main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    memset(f,0x3f,sizeof f);

    int n,p;
    cin>>n>>p;
    for(int i = 0; i<p; i++) f[i] = INF;
    for(int i = 1; i<=n; i++)
    {
        cin>>a[i];
        a[i] %= p;
        f[a[i]] = 1;
    }
    for(int i = 1; i<=n; i++)
    {
        for(int j = p - 1; j >= 0; j--)
        {
            
            //f[j] = min(f[j], f[(j-a[i]+p % p)]+1);
            int ne = (a[i]+j)%p;
            f[ne] = min(f[ne], f[j] + 1);
        }
    }
    cout<<f[0]<<endl;
    return 0;
}

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值