codeforces round379(div2)简易题解

本文解析了六道经典编程题目,包括字符串统计、数学优化、魔法战斗策略、国际象棋威胁判断、染色操作计数及位运算逆向求解等,通过具体代码示例深入浅出地讲解了解题思路。
Problem A

这是一个sb题,统计一下比较哪个多就好了

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int INF = 0x3f3f3f3f;
char str[200050];
int main(void)
{
    int n;
    while(~scanf("%d",&n)){
        scanf("%s",str);
        int l=0;
        for(int i=0;i<n;i++){
            if(str[i]=='A')l++;
        }
        if(l<n-l)puts("Danik");
        else if(l>n-l)puts("Anton");
        else puts("Friendship");
    }
    return 0;
}
Problem B

很明显2先组成256是最优的,然后剩下的用来组成32

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int INF = 0x3f3f3f3f;
int main(void)
{
    LL k2,k3,k5,k6;
    while(~scanf("%lld%lld%lld%lld",&k2,&k3,&k5,&k6)){
        LL sum=0;
        LL nm=min(k2,min(k5,k6));
        sum+=nm*(LL)256;
        k2-=nm;
        nm=min(k2,k3);
        sum+=nm*(LL)32;
        printf("%lld\n",sum);
    }
    return 0;
}
Problem C

因为第二种技能保证魔法值使用越多,威力越大,那么只需要枚举第一种技能,根据剩余的魔法值二分第二种技能的使用,答案取最小值即可

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int INF = 0x3f3f3f3f;
struct spell{
    LL atk,cost;
}a[200050],b[200050];
int cmp(spell a,spell b){
    return a.cost<b.cost;
}
int main(void)
{
    LL n,m,k;
    while(~scanf("%lld%lld%lld",&n,&m,&k)){
        LL x,s;
        scanf("%lld%lld",&x,&s);
        LL ans=n*x;
        a[0].atk=x;
        a[0].cost=0;
        for(int i=1;i<=m;i++){
            scanf("%lld",&a[i].atk);
        }
        for(int i=1;i<=m;i++){
            scanf("%lld",&a[i].cost);
        }
        for(int i=1;i<=k;i++){
            scanf("%lld",&b[i].atk);
        }
        for(int i=1;i<=k;i++){
            scanf("%lld",&b[i].cost);
        }
        sort(a+1,a+1+m,cmp);
        for(int i=0;i<=m;i++){
            if(a[i].cost>s)break;
            int tar=s-a[i].cost;
            int l=1,r=k;
            LL mx=0;
            while(l<=r){
                int mid=(l+r)>>1;
                if(b[mid].cost<=tar){
                    mx=max(mx,b[mid].atk);
                    l=mid+1;
                }
                else r=mid-1;
            }
            if(n-mx<=0)ans=0;
            else ans=min(ans,(LL)(n-mx)*a[i].atk);

        }
        printf("%lld\n",ans);
    }
    return 0;
}
Problem D

因为不能leap,所以说八个方向能够check的棋子只取决于距king最近的一个,判一下即可

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int INF = 0x3f3f3f3f;

struct node{
    char op;
    int x,y;
    node(){}
    node(char a,int b,int c){op=a,x=b,y=c;}
};
vector<node>lr,rl,r,c;
int cmp(node a,node b){
if(a.x!=b.x)return a.x<b.x;
return a.y<b.y;
}
int main(void)
{
    int n;
    scanf("%d",&n);
    int x,y;
    scanf("%d%d",&x,&y);
    for(int i=1;i<=n;i++){
        char str[2];
        int xx,yy;
        scanf("%s %d %d",str,&xx,&yy);
        node p(str[0],xx,yy);
        if(xx==x)r.push_back(p);
        if(yy==y)c.push_back(p);
        if(xx+yy==x+y)lr.push_back(p);
        if(yy-xx==y-x)rl.push_back(p);
    }
    sort(r.begin(),r.end(),cmp);
    sort(c.begin(),c.end(),cmp);
    sort(rl.begin(),rl.end(),cmp);
    sort(lr.begin(),lr.end(),cmp);
    int flag=0;
    int fl=-1,fr=r.size()+1;
    for(int i=0;i<r.size();i++){
        if(r[i].y<y)fl=i;
        if(r[i].y>y){fr=i;break;}
    }
    if(fl!=-1)if(r[fl].op=='R'||r[fl].op=='Q')flag=1;
    if(fr!=r.size()+1)if(r[fr].op=='R'||r[fr].op=='Q')flag=1;

    fl=-1,fr=c.size()+1;
    for(int i=0;i<c.size();i++){
        if(c[i].x<x)fl=i;
        if(c[i].x>x){fr=i;break;}
    }
    if(fl!=-1)if(c[fl].op=='R'||c[fl].op=='Q')flag=1;
    if(fr!=c.size()+1)if(c[fr].op=='R'||c[fr].op=='Q')flag=1;

    fl=-1,fr=rl.size()+1;
    for(int i=0;i<rl.size();i++){
        if(rl[i].y<y)fl=i;
        if(rl[i].y>y){fr=i;break;}
    }
    if(fl!=-1)if(rl[fl].op=='B'||rl[fl].op=='Q')flag=1;
    if(fr!=rl.size()+1)if(rl[fr].op=='B'||rl[fr].op=='Q')flag=1;

    fl=-1,fr=lr.size()+1;
    for(int i=0;i<lr.size();i++){
        if(lr[i].x<x)fl=i;
        if(lr[i].x>x){fr=i;break;}
    }
    if(fl!=-1)if(lr[fl].op=='B'||lr[fl].op=='Q')flag=1;
    if(fr!=lr.size()+1)if(lr[fr].op=='B'||lr[fr].op=='Q')flag=1;
    if(flag)puts("YES");
    else puts("NO");
    return 0;
}
Problem E

一个联通块内能够同时染色,所以先将联通块缩点,重建后的树保证相邻的两个点颜色不同,考虑以某个点为根,则需要染色的次数为距离它最远的点距离他的距离,设树的直径为r,那么ans=(r+1)/2

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int INF = 0x3f3f3f3f;
int fa[200050];
int co[200050];
int co2[200050];
int vis[200050];
struct edge{
    int v,nxt;
}e[400050];
int h[200050];
int siz;
struct ed{
    int u,v;
}pre[200050];
void init(){
    siz=0;
    memset(e,-1,sizeof(e));
    memset(h,-1,sizeof(h));
}
void add(int u,int v){
    e[siz].nxt=h[u];
    e[siz].v=v;
    h[u]=siz++;
}
int as=0;
int dfs(int u,int pr){
    int h1=0,h2=0;
    for(int i=h[u];~i;i=e[i].nxt){
        int v=e[i].v;
        if(v!=pr){
            int h=dfs(v,u)+1;
            if(h>h1)h2=h1,h1=h;
            else if(h>h2)h2=h;
        }
    }
    as=max(as,h1+h2);
    return h1;
}
int main(void)
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&co[i]);
    }
    init();
    for(int i=1;i<n;i++){
        int u,v;
        scanf("%d%d",&pre[i].u,&pre[i].v);
        add(pre[i].u,pre[i].v);
        add(pre[i].v,pre[i].u);
    }
    queue<int>mq;
    int cnt=1;
    fa[1]=1;
    co2[1]=co[1];
    vis[1]=1;
    mq.push(1);
    while(!mq.empty()){
        int u=mq.front();
        mq.pop();
        for(int i=h[u];~i;i=e[i].nxt){
            int v=e[i].v;
            if(!vis[v]){
                vis[v]=1;
                if(co[v]==co[u]){
                    fa[v]=fa[u];
                }
                else {
                    fa[v]=++cnt;
                    co2[cnt]=co[v];
                }
                mq.push(v);
            }
        }
    }
    init();
    for(int i=1;i<n;i++){
        int u=pre[i].u;
        int v=pre[i].v;
        if(fa[u]==fa[v])continue;
        add(fa[u],fa[v]);
        add(fa[v],fa[u]);
    }
    dfs(1,1);
    printf("%d\n",(as+1)/2);
    return 0;
}
Problem F

这道题的关键在于知道

(a|b)+(a&b)=a+b

因此
c[i]+b[i]=na[i]+j=1na[j]i=1nc[i]+b[i]=2nj=1na[j]

接下来我们就能够求出每个a[i],只需要判定是否合法即可
暴力判是n2的,但是我们可以按位考虑,这样是nlogn
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int INF = 0x3f3f3f3f;
LL b[200050];
LL c[200050];
LL a[220045];
LL num[55];
void check(int n,int &flag){
    for(int i=1;i<=n;i++){
        LL bb=0,cc=0;
        for(int j=50;j>=0;j--){
            bb<<=1;cc<<=1;
            if((1LL<<j)&a[i]){
                bb+=num[j];
                cc+=(LL)n;
            }
            else cc+=num[j];
        }
        if(bb!=b[i])flag=0;
        if(cc!=c[i])flag=0;
        if(!flag)return ;
    }
}
int main(void)
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%lld",&b[i]);
    }
    for(int i=1;i<=n;i++){
        scanf("%lld",&c[i]);
    }
    LL sum=0;
    for(int i=1;i<=n;i++){
        sum+=(b[i]+c[i]);
    }int flag=1;
    LL csum=sum;
    sum/=((LL)2*n);
    if(sum*(LL)2*n!=csum)flag=0;
    for(int i=1;i<=n;i++){
        a[i]=((b[i]+c[i])-sum)/n;
        if(a[i]*n!=(b[i]+c[i])-sum)flag=0;
        if(a[i]<0)flag=0;
    }
    memset(num,0,sizeof(num));
    if(flag)for(int i=1;i<=n;i++){
        LL p=a[i],k=0;
        while(p){
            if(p&1LL)num[k]++;
            p>>=1;
            k++;
        }
    }
    if(flag)check(n,flag);
    if(flag){
        for(int i=1;i<=n;i++)printf("%lld ",a[i]);
    }
    else puts("-1");
    return 0;
}
基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究(Matlab代码实现)内容概要:本文围绕“基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究”,介绍了利用Matlab代码实现配电网可靠性的仿真分析方法。重点采用序贯蒙特卡洛模拟法对配电网进行长时间段的状态抽样与统计,通过模拟系统元件的故障与修复过程,评估配电网的关键可靠性指标,如系统停电频率、停电持续时间、负荷点可靠性等。该方法能够有效处理复杂网络结构与设备时序特性,提升评估精度,适用于含分布式电源、电动汽车等新型负荷接入的现代配电网。文中提供了完整的Matlab实现代码与案例分析,便于复现和扩展应用。; 适合人群:具备电力系统基础知识和Matlab编程能力的高校研究生、科研人员及电力行业技术人员,尤其适合从事配电网规划、运行与可靠性分析相关工作的人员; 使用场景及目标:①掌握序贯蒙特卡洛模拟法在电力系统可靠性评估中的基本原理与实现流程;②学习如何通过Matlab构建配电网仿真模型并进行状态转移模拟;③应用于含新能源接入的复杂配电网可靠性定量评估与优化设计; 阅读建议:建议结合文中提供的Matlab代码逐段调试运行,理解状态抽样、故障判断、修复逻辑及指标统计的具体实现方式,同时可扩展至不同网络结构或加入更多不确定性因素进行深化研究。
### 完美排列问题分析 对于 Codeforces Round 1007 (Div. 2) 中的 **B. Perfecto** 问题,目标是找到一个长度为 \( n \) 的完美排列。如果这样的排列存在,则输出该排列;否则输出 `-1`。 #### 题目解析 题目定义了一个“完美排列”,其条件如下: - 对于任意位置 \( i \),满足 \( |p_i - p_{i+1}| = 1 \) 或者 \( |p_i - p_{i+1}| = n-1 \)[^2]。 这意味着相邻两个元素之间的差值要么等于 1(即连续),要么等于 \( n-1 \)(即首尾相连)。 #### 解题方法 通过观察和归纳可以得出以下结论: - 当 \( n \% 3 == 0 \) 或 \( n \% 3 == 2 \) 时,无法构建出符合上述条件的完美排列。 - 而当 \( n \% 3 == 1 \) 时,可以通过特定构造方式生成所需排列。 具体实现逻辑如下: ```cpp #include <bits/stdc++.h> using namespace std; void solve() { int n; cin >> n; if (n % 3 != 1) { // 如果不符合模数条件 cout << "-1\n"; return; } vector<int> res(n); bool flag = true; // 控制交替模式 for(int i = 0;i < n;i++) { if(flag){ res[i] = i + 1; } else{ res[i] = ((n-i)+1)%n; if(res[i]==0)res[i]=n; } flag=!flag; } for(auto num : res){ cout<<num<<" "; } } int main(){ ios::sync_with_stdio(false); cin.tie(0); int t=1; while(t--){ solve(); } } ``` 此代码片段实现了基于输入大小 \( n \) 来判断是否存在合法解并输出相应结果的功能。 #### 关键点说明 - 判断依据来源于对不同余数值下能否形成循环结构的研究成果。 - 构造过程中采用交替填充策略来确保最终序列能够满足绝对差的要求。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值