比赛链接

题解

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;
}