牛客小白月赛80(A-D我比较lj,只能补到D)

85 阅读3分钟

这个月赛ADA-D都是属于基本题,DD可能稍微有一点结合,然后我就不会了,我是fwfw

A-矩阵快速幂签到_牛客小白月赛80 (nowcoder.com)

分析

乍一看还以为真的是快速幂,好多小朋友WAWA了,然后仔细一看,其实经过移项不难发现a[i]a[i1]=a[i1]a[i2]a[i]-a[i-1]=a[i-1]-a[i-2],于是乎很显然是等差数列,我们可以求出通项公式a[n]=n+1a[n]=n+1,所以答案就是输出(x+1)(x+1)%modmod即可。

代码

#include <bits/stdc++.h>

#define ll long long 
using namespace std;
const int mod=998244353;
int main(){
	
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	ll x;
	cin>>x;
	cout<<(x+1)%mod;
	return 0;
} 

B-第一次放学_牛客小白月赛80 (nowcoder.com)

分析

模拟+贪心,我们将每个班级的人数存起来(数组和mapmap皆可),然后我们遍历如果人数nk≤n-k,我们就不停的取maxmax,否则说明可以取到nkn-k

代码

#include <bits/stdc++.h>
using namespace std;
const int N=100010;
int n,a[N],m,k;
map<int,int> mp;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        mp[a[i]]++;
    }
    int ans=0;
    for(auto it:mp){
        if(it.second<=n-k) ans=max(ans,it.second); 
        else ans=n-k;
    }
    cout<<ans;
    return 0;
}

D-又放学辣(进阶)_牛客小白月赛80 (nowcoder.com)

CCDD这里就放一个DD,CC数据范围很小,其实很容易,就是可以单纯二分来解决,复杂度是O(m2logm)O(m^2logm),很显然可以过,我们遍历每个班级,二分一个最小留下来的最大人数midmid,使用l+r>>1l+r>>1型的二分找出最大值,然后把mid>mid的都求和和kk比较大小即可,但是DD加强了数据范围,就要用前缀和来优化,这个其实是一个二分套二分的过程,时间复杂度是O(mlog2m)O(mlog^2m),我们使用两个数组分别记录排序前和后的班级人数,下面二分不变,上面二分里面再套一个二分来寻找排完序之后>mid>mid的最小的下标值,这里要注意,如果拖堂的班级人数>mid>mid,要提前减去itmidit-mid。但是有O(mlogm)O(mlogm)的做法,可惜我不会(QAQ)(QAQ)CC代码

#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
int n,m,k;
map<int,int> mp;
const int N=1e6+10;
int a[N];
int sum[N];
bool check(int id,int mi){
    int ans=0;
    for(int i=1;i<=m;i++){
        if(i!=id){
            ans+=max(0,sum[i]-mi);
        }
    }
    return ans<=k;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin>>n>>m>>k;
    memset(sum,0,sizeof sum);
    for(int i=1;i<=n;i++){
        cin>>a[i];
        sum[a[i]]++;
    }
    for(int i=1;i<=m;i++){
        if(n-sum[i]<k) cout<<-1<<" ";
        else{
            int l=0,r=1e6;
            while(l<r){
                int mid=l+r>>1;
                if(check(i,mid)) r=mid;
                else l=mid+1;
            }
            cout<<l<<" ";
        }
    }
    return 0;
}

DD代码

#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
int n,m,k;
const int N=1e6+10;
int a[N];
int sum[N],res[N];
int pre[N];
bool check(int id,int mi){
    int ans=0;
    if(sum[id]>mi) ans-=sum[id]-mi;
    if(pre[m]<mi) return true;
    int l=1,r=m;
    while(l<r){
        int mid=l+r>>1;
        if(pre[mid]<=mi) l=mid+1;
        else r=mid;
    }
    ans+=res[m]-res[l-1]-(m-l+1)*mi;
    //cout<<ans<<endl;
    return ans<=k;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    cin>>n>>m>>k;
    memset(sum,0,sizeof sum);
    for(int i=1;i<=n;i++){
        cin>>a[i];
        sum[a[i]]++;
        pre[a[i]]++;
    }
    sort(pre+1,pre+m+1);
    res[0]=0;
    for(int i=1;i<=m;i++){
        res[i]=res[i-1]+pre[i];
    }
    for(int i=1;i<=m;i++){
        if(n-sum[i]<k) cout<<-1<<" ";
        else{
            int l=0,r=1e6;
            while(l<r){
                int mid=l+r>>1;
                if(check(i,mid)) r=mid;
                else l=mid+1;
            }
            cout<<l<<" ";
        }
    }
    return 0;
}