AtCoder Beginner Contest 307

A.暴力统计即可

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <unordered_map>
#include <map>
#include <set>
#include <unordered_set>
#include <cmath>
using namespace std;
const int N = 2e5+10;
#define int long long
typedef pair<int, int> PII;
int n,m;
int a[N];
signed main(){
    cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
    cin>>n;
    for(int i=1;i<=n;i++){
        int cnt=0;
        for(int j=1;j<=7;j++)
        {
            int x;cin>>x;
            cnt+=x;
        }
        cout<<cnt<<" ";
    }
}

B.也是暴力即可

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <unordered_map>
#include <map>
#include <set>
#include <unordered_set>
#include <cmath>
using namespace std;
const int N = 2e5+10;
#define int long long
typedef pair<int, int> PII;
int n,m;
int a[N];
string s[N];
signed main(){
    cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
    cin>>n;
    for(int i=1;i<=n;i++) cin>>s[i];

    for(int i=1;i<=n;i++){
        for(int j=i+1;j<=n;j++)
        {
            string t=s[i]+s[j];
            int l=0,r=t.size()-1;
            bool f=true;
         //   cout<<t<<"\n";
            while(l<=r){
                if(t[l]==t[r])
                {
                    l++,r--;    
                }
                else{
                    f=false;break;
                }
            }
            if(f){
               cout<<"Yes\n";return 0; 
            }
        }
    }
    cout<<"No\n";
}

C.没写毒瘤题

D

栈模拟

碰到)并且栈里面有(就直接丢弃字符串后面的字符串直到碰到第一个(才停止

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include<stack>
#include <unordered_map>
#include <map>
#include <set>
#include <unordered_set>
#include <cmath>
using namespace std;
const int N = 2e5+10;
#define int long long
typedef pair<int, int> PII;
int n,m;
int a[N];
//string s[N];
signed main(){
    cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
    cin>>n;
    string s;
    cin>>s;
    stack<char> st;
    string res;
    for(int i=0;i<s.size();i++)
    {
        if(s[i]!=')'&&s[i]!='(')
        {
            res.push_back(s[i]); continue;
        }
        if(st.empty()) st.push(s[i]),res.push_back(s[i]);
        else{
            if(st.size()&&st.top()=='('&&s[i]==')')
            {
                while(res.size()&&res.back()!='(') res.pop_back();
                res.pop_back();
                st.pop();
                continue;
            }
            else st.push(s[i]),res.push_back(s[i]);
        }
    }
    cout<<res;
}

E.DP

状态前i个人,每个人相邻整数不同,且第i个人和第一个人整数相同(1)/不相同(0)

把环变成链即可

解释一下状态转移

f[i][0]:由两个方向转移 可以由前面f[i-1][0]*(m-2)由于要和第一个数不同且和前面一个数不同

f[i-1][1]*(m-1)因为前面一个数和第一个数相同,所以能选m-1个数

f[i][1]:只能由f[i-1][0]只能选第一个数的编号

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include<stack>
#include <unordered_map>
#include <map>
#include <set>
#include <unordered_set>
#include <cmath>
using namespace std;
const int N = 1e6+10,mod=998244353;
#define int long long
typedef pair<int, int> PII;
int n,m;
int f[N][3];
//string s[N];
signed main(){
    cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
    cin>>n>>m;
    
    f[1][1]=m;
    for(int i=1;i<n;i++){
        f[i+1][0]=(f[i][0]*(m-2)+f[i][1]*(m-1))%mod;
        f[i+1][1]=f[i][0]%mod;
    }
    cout<<f[n][0]%mod;
}

F.

首先把没感染过的点全部进行入队(可以看错建立了个虚拟源点进行了第一轮感染)

因为每天的x感染距离不同

所以我们用另一个堆去记录这天扩展的到的点,如果扩展不到就继续放入到第一个堆

第一个堆就是记录哪些点还没被感染,第二个堆才是用来扩展点的

如果没被感染就是权值小于x,那么距离变成当前点到没感染点的权值,因为这个求得是最短路,可以顺便更新到没感染点的最短路

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include<stack>
#include <unordered_map>
#include <map>
#include <set>
#include <unordered_set>
#include <cmath>
using namespace std;
const int N = 1e6+10,mod=998244353;
#define int long long
typedef pair<int, int> PII;
int n,m,k,d;
vector<PII> g[N];
signed main(){
    cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int x,y,z;cin>>x>>y>>z;
        g[x].push_back({y,z});
        g[y].push_back({x,z});
    }
    cin>>k;
    vector<int> res(n+1,-1);
    priority_queue<PII,vector<PII>,greater<PII>> q;
    for(int i=1;i<=k;i++){
        int x;cin>>x;
        res[x]=0;
        for(auto&e:g[x]){
            if(res[e.first]==-1)
            q.push({e.second,e.first});
        }
    }
    cin>>d;
    for(int i=1;i<=d;i++)
    {
        priority_queue<PII,vector<PII>,greater<PII>> q1;
        int x;cin>>x;
        while(q.size())
        {
            auto p=q.top();
            if(p.first>x) break;
            q.pop();
            if(res[p.second]!=-1) continue;
            q1.push(p);
        }
        while(q1.size())
        {
            auto p=q1.top();
            q1.pop();
            if(res[p.second]!=-1) continue;
            auto y=p.second;
            res[y]=i;
            for(auto e:g[y]){
                if(res[e.first]==-1)
                {
                    if(p.first+e.second<=x){
                        q1.push({p.first+e.second,e.first});
                    }
                    else{
                        q.push({e.second,e.first});
                    }
                }
            }
        }
    }
    for(int i=1;i<=n;i++) cout<<res[i]<<"\n";
}

G.

首先对于两个操作,不会改变总和,且要求相差最大为1

那么最多只能是两个不同的数

我们设x=sum/n,y=sum%n

=x=sum/n,y=x+1

因为sum不能整除多出来了只能相加1

所以dp可设置成

前i个数能用j个+1

转移有点麻烦

我们要记录前面数的总和,求到当前数的时候,因为我们已经知道前面已经用了(y-j)个加一

且前面数的总和是pre,有(y-j)个数是x+1,另外的(i-(y-j))个数是x

那么我们就能准确的算出当前数变成什么数了

如果还能用+1

f[i][j]=min(f[i][j],f[i-1][j]+abs(cur-x));就是不用+1,把当前数变成x需要的次数

  f[i][j-1]=min(f[i][j-1],f[i-1][j]+abs(cur-(x+1)));就是把当前数变成x+1需要的次数,用来更新发f[i][j-1]

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include<stack>
#include <unordered_map>
#include <map>
#include <set>
#include <unordered_set>
#include <cmath>
using namespace std;
const int N = 1e6+10,mod=998244353;
#define int long long
int INF=1e18;
typedef pair<int, int> PII;
int n,m;
int a[N];
int f[5010][5010];
signed main(){
    cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
    cin>>n;
    int s=0;
    for(int i=1;i<=n;i++) cin>>a[i],s+=a[i];
    int x=s/n,y=s%n;
    
    if(y<0){
        y=n+y;
        x--;
    }
    memset(f,0x3f,sizeof(f));
    f[0][y]=0;
    int pre=0;
    for(int i=1;i<=n;i++)
    {
        int z=a[i];
        for(int j=0;j<=y;j++)//还有j个x+1能用
        {
            int cur=z-(x*(i-1)-pre + y-j);
            f[i][j]=min(f[i][j],f[i-1][j]+abs(cur-x));
            
            if(j) 
            f[i][j-1]=min(f[i][j-1],f[i-1][j]+abs(cur-(x+1)));
        }
        pre+=z;
    }

    cout<<f[n][0];
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值