AtCoder Regular Contest 108

AtCoder Regular Contest 108

传送门

A - Sum and Product

思路:

联立方程,得到二次函数,易知函数具有单调性, n \sqrt{n} n 枚举

#include <iostream>
using namespace std;
typedef long long ll;
ll p,s;
int main(){
    cin>>s>>p;
    int ok=0;
    for(ll i=1;s-i>=1;i++){
        if(s*i-i*i==p){
            ok=1;
            break;
        }else if(s*i-i*i>p){
            break;
        }
    }
    if(ok) cout<<"Yes\n";
    else cout<<"No\n";
}


Abbreviate Fox

思路:

模拟:

可以看出直接模拟删除 f o x fox fox就行。

栈:

可以用栈将失配压入栈内,当一个 f o x fox fox配对成功删除,就出栈上次代配对的,具体操作看代码,时间复杂度 O ( n ) O(n) O(n)

#include <iostream>
#include <vector>
using namespace std;
const int N=3e5+7;
int n;
char a[N];
vector <int> sa;
int main(){
    cin>>n;
    cin>>(a+1);
    int ok=0,ans=0;
    for(int i=1;i<=n;i++){
        if(ok==1&&a[i]=='o'){
            ok=2;
        }else if(ok==2&&a[i]=='x'){
            ans++;
            if(!sa.empty()){
                ok=sa.back();
                sa.pop_back();
            }else{
                ok=0;
            }
        }else{
            if(a[i]=='f'){
                sa.push_back(ok);
                ok=1;
            }else{
                sa.push_back(ok);
                ok=0;
            }
        }
    }
    cout<<n-3*ans<<"\n";
}

C - Keep Graph Connected

思路:

结论:

因为可以删边成棵树

那么图连通,那么一定有解,那么其结构将会是棵树。

贪心:

1.如果上个节点已占有边,那么当前节点优先选能占有下个节点的边且合法的值。

2.如果上个节点未占有边,那么当前节点只能选边的值。

#include <iostream>
using namespace std;
const int N=2e5+7;
struct node{int to,w,next;}e[N*2];
int n,m,vis[N],ans[N];
int head[N],tot;
void add(int u,int v,int w){
    e[++tot].to=v;
    e[tot].w=w;
    e[tot].next=head[u];
    head[u]=tot;
}
void dfs(int p,int fa,int pre,int ok){
    vis[p]=1;
    int col=0;
    if(ok){
        for(int i=head[p];i;i=e[i].next){
            if(vis[e[i].to]) continue;
            int w=e[i].w;
            if(w!=ans[fa]&&w!=pre){
                col=w;
                break;
            }
        }
        if(!col){
            for(int i=1;i<=n;i++){
                if(i!=ans[fa]&&i!=pre){
                    col=i;
                    break;
                }
            }
        }
        ans[p]=col;
        for(int i=head[p];i;i=e[i].next){
            int v=e[i].to,w=e[i].w;
            if(vis[v]) continue;
            dfs(v,p,w,col==w);
        }
    }else{
        ans[p]=pre;
        for(int i=head[p];i;i=e[i].next){
            int v=e[i].to,w=e[i].w;
            if(vis[v]) continue;
            dfs(v,p,w,pre==w);
        }
    }
}
int check(){
    for(int i=1;i<=n;i++){
        if(!vis[i]) return 0;
    }
    return 1;
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int u,v,w;
        cin>>u>>v>>w;
        add(u,v,w),add(v,u,w);
    }
    for(int i=1;i<=n;i++){
        dfs(i,0,0,1);
        break;
    }
    if(check()){
        for(int i=1;i<=n;i++) cout<<ans[i]<<"\n";
    }else{
        cout<<"No\n";
    }
}


D - AB

思路:

大讨论:

如果 C A A = A , C A B = A C_{AA}=A,C_{AB}=A CAA=A,CAB=A。显然答案是1

如果 C A B = B , C B B = B C_{AB}=B,C_{BB}=B CAB=B,CBB=B。显然答案是1

如果 C A B = A , C A A = B , C B A = B C_{AB}=A,C_{AA}=B,C_{BA}=B CAB=A,CAA=B,CBA=B,或 C A B = B , C B B = A , C B A = A C_{AB}=B,C_{BB}=A,C_{BA}=A CAB=B,CBB=A,CBA=A

  • A _ _ A B A\_\_AB A__AB中间将插的是任意组合,即答案为 2 n − 3 2^{n-3} 2n3

如果 C A B = A , C A A = B , C B A = A C_{AB}=A,C_{AA}=B,C_{BA}=A CAB=A,CAA=B,CBA=A,或 C A B = B , C B B = A , C B A = B C_{AB}=B,C_{BB}=A,C_{BA}=B CAB=B,CBB=A,CBA=B

  • 将是构成类是为不含连续0的01序列的个数,即答案为fib[n-1]。
#include <iostream>
using namespace std;
typedef long long ll;
const int N=1007;
const ll mod=1e9+7;
int n;
ll fib[N];
char c1,c2,c3,c4;
ll ksm(ll x,ll p){
    ll res=1;
    while(p){
        if(p&1) res=res*x%mod;
        p/=2;
        x=x*x%mod;
    }
    return res;
}
void init(){
    fib[1]=1,fib[2]=1;
    for(int i=3;i<=n;i++){
        fib[i]=(fib[i-1]+fib[i-2])%mod;
    }
}
int main(){
    cin>>n;
    cin>>c1>>c2>>c3>>c4;
    if(n==2){
        cout<<1<<"\n";
        return 0;
    }
    init();
    if((c2=='A'&&c1=='A')||(c2=='B'&&c4=='B')){
        cout<<"1\n";
    }else if(c2=='A'&&c1=='B'&&c3=='B'){
        cout<<ksm(2,n-3)<<"\n";
    }else if(c2=='B'&&c4=='A'&&c3=='A'){
        cout<<ksm(2,n-3)<<"\n";
    }else{
        cout<<fib[n-1]<<"\n";
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值