花开堪折直须折,|

园龄:粉丝:关注:

2025牛客寒假算法基础集训营4

K

小学加减乘除法,取最大值

I

利用后缀数组的思想(前缀也可以)

#include<bits/stdc++.h>

using namespace std;

int n;
string s;

int t;
string x="uwawauwa";
void solve(){
    cin>>n;
    cin>>s;
    int ans=0;
    for(int i=0;i<n;++i){
        if(s[i]=='u'){
            int j=i+1;
            if(s[j]=='u')continue;
            while(s[j]!='u' && j<n) ++j;
            if(j>=n) break;
            string y;
            for(int k=j;k<=j+7;++k)    y+=s[k];
            if(x==y) ++ans;
        }
    }
    cout<<ans<<endl;
    return ;
}
int main(){
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}


E

类似于八皇后问题

利用集合的知识,对于一个位置击败的敌人,应该是两条斜线上的敌人总和-该位置的敌人

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long 
int t;
int n,m;
const int maxn=1e3+10;
map<int,ll>mp1,mp2;
int a[maxn][maxn];

void solve(){
    cin>>n>>m;
    mp1.clear(),mp2.clear();
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j){
            int x;
            cin>>x;
            a[i][j]=x;
            mp1[i+j]+=x;
            mp2[i-j]+=x;
        }
    ll ans=0;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j){
            int x=a[i][j];
            ans=max(ans,mp1[i+j]+mp2[i-j]-x);
        }
    cout<<ans<<"\n";
    return ;
    
    
}
int main(){
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}

B

按照题意暴力检验就行
(写的有点shi

#include<bits/stdc++.h>

using namespace std;
#define ll long long 

const int mod=1e9+7;
int n;
int t;
int ans=0;
string s;
const int maxn=1e3;
bool book[maxn];
int get(){
    int p=0,q=0;
    for(int i=0;i+1<n;++i){
        if(s[i]=='0' && s[i+1]=='1') ++p;
        if(s[i]=='1' && s[i+1]=='0') ++q;
    }
    return p==q?1:0;
}
void check(){//找一个确定的字符串的数量
//	cout<<s<<"\n";
	for(int i=0;i<n;++i){
		s[i]=(s[i]=='1'?'0':'1');
	
		ans+=get();
		ans%=mod; 
	
		s[i]=(s[i]=='1'?'0':'1');
	}
}
void dfs(int x){
	int i;
	for(i=x+1;i<n;++i){
        if(!book[i]) continue;
        else break;
    }
	if(i>=n) check();//字符串已经确定了
	else {
		s[i]='0';
	    dfs(i);
	    s[i]='1';
		dfs(i);
	}
	
}
void solve(){
    cin>>n;cin>>s;
    memset(book,0,sizeof(book));
    for(int i=0;i<n;++i) if(s[i]=='?') book[i]=1;
    dfs(-1);
    cout<<ans%mod<<"\n";
}
int main(){
    cin>>t;
    while(t--){
        ans=0;
        solve();
    }
    return 0;
}

C

按照上题的做法,n[1,2×105]一定会TLE

因为需要知道一个字符串是否平衡,我们一定要遍历整个字符串,而可能的字符串会有2p种,

所以我们只能考虑寻找该字符串的性质,以期望快速检验一个字符串是否平衡

  • 寻找性质
    一个字符串是否平衡取决于01,10的数量是否相等,但是一个一个遍历一定会超时
    • 首先,我们可以发现,连续的,0,或者,1可以看成一个0,或者1,处理,因为00,11不会对01,10,的数量有影响
    • 所以我们拿到一个字符串之后,一定可以化简为 1010101,010101,101010,0101010,这四种情况,只是长度不同
    • 这时,我们会发现首尾相同的字符串平衡

性质: 首位相同的字符串平衡

  • 分类讨论
    我们设总的'?'数量是cnt
    同时还要考虑翻转一个字符的字符串的数量
  1. 首尾都是'?'

1.1首尾相同
ans=2cnt22(n2)=2cnt1(n2),前后不能翻转
1.2首位不同
ans=2cnt222=2cnt12,不同的有两种情况,翻转后又有两种
ans=2cnt1n
2. 头或者尾是'?'
2.1首尾相同
ans=2cnt1(n2)=2cnt1(n2),前后不能翻转
2.2首尾不同
ans=2cnt12 要么翻转头,要么翻转尾巴
ans=2cnt1n

  1. 首尾确定
    3.1 首尾相同
    ans=2cnt(n2)
    3.2 首尾不同
    ans=2cnt2
    ans=2cntn

1,2结论相同,合并输出

注意,长度为1时的讨论,看代码你应该懂

点击查看代码
#include<bits/stdc++.h>

using namespace std;
int n;
#define ll long long 
string s;
int t;
const int mod=1e9+7;
int quick_pow(int a,int b){
    if(b<0) return 1;
    int cnt=1;
    while(b){
        if(b&1) cnt=(1ll*cnt*a)%mod;
        a=(1ll*a*a)%mod;
        b>>=1;
    }
    return cnt;
}
void solve(){
    cin>>n;
    cin>>s;
    s=" "+s;
    if(n==1){
        if(s[1]=='?') puts("2");
        else puts("1");
        return ;
    }
    int cnt=0;
    for(int i=1;i<=n;++i) if(s[i]=='?') ++cnt;
    int ans=0;
    
    int y=quick_pow(2,cnt-1)%mod,x=quick_pow(2,cnt)%mod;
    if(s[1]!='?' && s[n]!='?'){
        if(s[1]==s[n]) ans=1ll*x*(n-2)%mod;
        else ans=1ll*x*2%mod;
    }
    else ans=1ll*y*n%mod;
    cout<<ans<<"\n";
    return ;
}
int main(){
    cin.tie(0);
    cout.tie(0);
    
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}

D

可以任意排列,相当于字符可以放在任意位置

很自然地想到,我们可以尽量用短的字符串消除长的字符串中的一些字符

但是一般情况下,短的字符串中会存在一些字符我们无法消除,所以一定我们需要改变a中sum个字符

而在长字符串中

  • 如果字符的数量是偶数,那他们可以因为回文串自我消除
  • 如果字符的数量是奇数,那他们偶数个字符可以自我消除,剩下的字符一定要自己消除,记为ans

那么其实可以考虑ans的一部分字符去消除sum的字符,也可以用sum的字符消除ans,这取决于两者大小关系

  1. anssum,最终答案,sum

  2. ans>sum,最终答案,sum+anssum2

点击查看代码
#include<bits/stdc++.h>

using namespace std;
int t;
void solve(){
    string a,b;
    map<int,int>mp;
    int n,m;
    int sum=0,ans=0;
       cin>>n>>m>>a>>b;
    if(n<m){//确保a是长串
        swap(a,b);
        swap(n,m);
    }
   
    for(int i=0;i<n;++i) mp[a[i]]++;
    for(int i=0;i<m;++i) 
        if(mp[b[i]])mp[b[i]]--;
        else sum++;//a中需要改变的字符
    for(auto [x,y]:mp)
        if(y&1) ++ans;
    if(sum>=ans) cout<<sum<<endl;
    else cout<<sum+floor((ans-sum)/2)<<endl;
}
int main(){
    cin>>t;
    while(t--){
        solve();
    }return 0;
}

F

这个思路相当好

我谨且做一点总结:
一开始,也觉得似曾相识,我们是否能够直接搜出前k大的数,因为,这里明显既没有性质,也没有算法可以利用

很容易都想到,每个数都要%p,之后根据思路的搜索找到前k大的值

其实我们并没有直接搜索前k大的数,而是搜索最有可能的前k大的数,放入堆中,输出k个值后截止

这里融入了搜索的思想,剪枝,不盲目地搜索,而且保证了搜索所有可能的值

所以这题:我们学到了什么?

在只能暴力的情况下,选择最优雅的暴力

点击查看代码
#include<bits/stdc++.h>

using namespace std;
#define ll long long 
typedef pair<int,int> pii;
int n,p,k;
const int maxn=2e5+10;
int t;
int a[maxn];
void solve(){
    cin>>n>>p>>k;
    for(int i=1;i<=n;++i) cin>>a[i],a[i]%=p;
    sort(a+1,a+1+n);
    set<pii> sets;
    priority_queue<array<int,3>>q;
    q.push({(a[n-1]+a[n])%p,n-1,n});
    for(int i=n;i>=1;--i){
        int j=lower_bound(a,a+i,p-a[i])-a-1;
        if(j<1) continue;
        q.push({(a[i]+a[j])%p,j,i});
    }
    while(!q.empty() && k){
        auto [val,i,j]=q.top();
        q.pop();
        if(sets.contains({i,j})) continue;
        sets.insert({i,j});
        cout<<val<<" ";
        k--;
        if(i>1) q.push({(a[i-1]+a[j])%p,i-1,j});
        if(i<j-1) q.push({(a[i]+a[j-1])%p,i,j-1});
    }
    while(k--) cout<<-1<<" ";
    puts("");
}
int main(){
    cin>>t;
    while(t--){
        solve();
    }return 0;
}

A

官方题解

解释一下

1.因为是等概率随机生成,其实求期望就是:求值/(总的对数)

2.除去总的对数要还要取模,让我想起了逆元ap2=x(modM),不会的点这里

本文作者:归游

本文链接:https://www.cnblogs.com/guiyou/p/18703000

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   归游  阅读(4)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起