『比赛』Codeforces Round #369 (Div. 2) 5题总结

本文提供了CodeForces平台上的多个经典题目解析,包括贪心算法、模拟题、动态规划、强连通分量及概率计算等内容,旨在帮助读者理解和掌握不同类型的算法题解思路。

题目链接:http://codeforces.com/contests

A. Bus to Udayland

分析:就是一个手速的贪心题,看懂英文就好了…

/* Author:GavinjouElephant
 * Title:
 * Number:
 * main meanning:
 *
 *
 *
 */


#include <iostream>
using namespace std;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <vector>
#include <set>
#include <cstdlib>
#include <map>
#include <queue>
//#include<initializer_list>
//#include <windows.h>
//#include <fstream>
//#include <conio.h>
#define MaxN 0x7fffffff
#define MinN -0x7fffffff
#define lson 2*k
#define rson 2*k+1
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=1005;
int Scan()//读入整数外挂.
{
    int res = 0, ch, flag = 0;

    if((ch = getchar()) == '-')             //判断正负
        flag = 1;

    else if(ch >= '0' && ch <= '9')           //得到完整的数
        res = ch - '0';
    while((ch = getchar()) >= '0' && ch <= '9' )
        res = res * 10 + ch - '0';
    return flag ? -res : res;
}
 void Out(int a)    //输出外挂
 {
     if(a>9)
         Out(a/10);
     putchar(a%10+'0');
 }

char seat[maxn][10];
int n;
int main()
{
#ifndef ONLINE_JUDGE
    freopen("coco.txt","r",stdin);
    freopen("lala.txt","w",stdout);
#endif
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%s",seat[i]);
    }
    bool flag=true;
    for(int i=0;i<n;i++)
    {
        if(seat[i][0]=='O'&&seat[i][1]=='O')
        {
              flag=false;
              seat[i][0]=seat[i][1]='+';
              break;
        }
        if(seat[i][3]=='O'&&seat[i][4]=='O')
        {
              flag=false;
              seat[i][3]=seat[i][4]='+';
              break;
        }

    }

    if(flag) printf("NO\n");
    else
    {
        printf("YES\n");
        for(int i=0;i<n;i++) printf("%s\n",seat[i]);
    }
    return 0;
}

B. Chris and Magic Square

分析:这是一道模拟题,看样例就知道,就是跟你一个阵,里面有一个位置是空的(0),然后让你填入一个>0的数,
使得行之和,列之和,对角线之和都相等. 这是一道模拟题,很简单…,按着题意写就行了

/* Author:GavinjouElephant
 * Title:
 * Number:
 * main meanning:
 *
 *
 *
 */


#include <iostream>
using namespace std;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <vector>
#include <set>
#include <cstdlib>
#include <map>
#include <queue>
//#include<initializer_list>
//#include <windows.h>
//#include <fstream>
//#include <conio.h>
#define MaxN 0x7fffffff
#define MinN -0x7fffffff
#define lson 2*k
#define rson 2*k+1
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=1e5+10;
int Scan()//读入整数外挂.
{
    int res = 0, ch, flag = 0;

    if((ch = getchar()) == '-')             //判断正负
        flag = 1;

    else if(ch >= '0' && ch <= '9')           //得到完整的数
        res = ch - '0';
    while((ch = getchar()) >= '0' && ch <= '9' )
        res = res * 10 + ch - '0';
    return flag ? -res : res;
}
 void Out(int a)    //输出外挂
 {
     if(a>9)
         Out(a/10);
     putchar(a%10+'0');
 }

 int a[505][505];
 ll rsum[505];
 ll lsum[505];
 ll lx;
 ll rx;
 int n;
 ll M;
 int si,sj;
 void solve()
 {
     if(n==0) {printf("1\n");return;}

     ll c=M-rsum[si];
     if(c<=0)  {printf("-1\n");return;}

     rsum[si]=M;

     lsum[sj]+=c;

     if((si+sj)==n)rx+=c;
     if(si==sj)lx+=c;

     if(lx!=rx||lx!=M){printf("-1\n");return;}

     for(int i=0;i<n;i++)
     {
         if(rsum[i]!=M){printf("-1\n");return;}
     }

     for(int j=0;j<n;j++)
     {
         if(lsum[j]!=M){printf("-1\n");return;}
     }
     printf("%I64d\n",c);
 }
int main()
{
#ifndef ONLINE_JUDGE
    freopen("coco.txt","r",stdin);
    freopen("lala.txt","w",stdout);
#endif
    scanf("%d",&n);
    n--;

    memset(rsum,0,sizeof(rsum));
    memset(lsum,0,sizeof(lsum));
    lx=0;
    rx=0;

    M=(long long)-INF;


    for(int i=0;i<=n;i++)
    {
        for(int j=0;j<=n;j++)
        {
            scanf("%d",&a[i][j]);
            if(a[i][j]==0){ si=i;sj=j;}

            rsum[i]+=a[i][j];
            lsum[j]+=a[i][j];

            if(i==j)lx+=a[i][j];
            if(i+j==n) rx+=a[i][j];
        }
        M=max(M,rsum[i]);
    }


    solve();




    return 0;
}

C. Coloring Trees

分析: 这道题扎眼一看就是个dp,我几乎没怎么想,我的代码那时坑在了边界值,忘记处理了,简直天煞,浪费了好多时间也没A掉, dp[i][j][k]:代表我当前所要染色的位置为i,我当前染了第j种颜色,k为连续的个数
这个dp很容易推,所以不多讲.

/* Author:GavinjouElephant
 * Title:
 * Number:
 * main meanning:
 *
 *
 *
 */


#include <iostream>
using namespace std;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <vector>
#include <set>
#include <cstdlib>
#include <map>
#include <queue>
//#include<initializer_list>
//#include <windows.h>
//#include <fstream>
//#include <conio.h>
#define MaxN 0x7fffffff
#define MinN -0x7fffffff
#define lson 2*k
#define rson 2*k+1
typedef long long ll;
const ll INF=0x3f3f3f3f;
const ll maxn=(ll)100000000000+10;
ll Scan()//读入整数外挂.
{
    ll res = 0, ch, flag = 0;
    if((ch = getchar()) == '-')             //判断正负
        flag = 1;

    else if(ch >= '0' && ch <= '9')           //得到完整的数
        res = ch - '0';
    while((ch = getchar()) >= '0' && ch <= '9' )
        res = res * 10 + ch - '0';
    return flag ? -res : res;
}
void Out(ll a)    //输出外挂
{
    if(a>9)
        Out(a/10);
    putchar(a%10+'0');
}
ll n,m,k;
ll dp[105][105][105];//现在选择第i个,上一个选择是C,现在不同的长度是105.
ll p[105][105];

ll tree[105];

int main()
{
    scanf("%I64d%I64d%I64d",&n,&m,&k);
    for(ll i=0; i<=n; i++)
    {
        for(ll j=0; j<=m; j++)
        {
            for(ll K=0; K<=k; K++)
            {
                if(i==0&&K==0)
                {
                    dp[i][j][K]=0;
                    continue;
                }
                dp[i][j][K]=maxn;
            }
        }
    }
    for(ll i=1; i<=n; i++)
    {
        scanf("%I64d",&tree[i]);
    }
    for(ll i=1; i<=n; i++)
    {
        for(ll j=1; j<=m; j++)
        {
            scanf("%I64d",&p[i][j]);
        }
    }


    for(ll i=1; i<=n; i++)
    {
        for(ll t=1; t<=k; t++)
        {
            if(tree[i]==0)
            {
                for(ll se=1; se<=m; se++)
                {
                    if(i!=1)
                    {
                        for(ll lse=1; lse<=m; lse++)
                        {
                            if(se==lse) dp[i][se][t]=min(dp[i][se][t],p[i][se]+dp[i-1][lse][t]);
                            else   dp[i][se][t]=min(dp[i][se][t],p[i][se]+dp[i-1][lse][t-1]);
                        }
                    }
                    else
                    {
                        dp[i][se][t]=min(dp[i][se][t],p[i][se]+dp[i-1][0][t-1]);
                    }
                }

            }
            else
            {
                ll se=tree[i];
                if(i!=1)
                {
                    for(ll lse=1; lse<=m; lse++)
                    {
                        if(se==lse) dp[i][se][t]=min(dp[i][se][t],dp[i-1][lse][t]);
                        else   dp[i][se][t]=min(dp[i][se][t],dp[i-1][lse][t-1]);
                    }
                }
                else
                {
                     dp[i][se][t]=min(dp[i][se][t],dp[i-1][0][t-1]);

                }
            }
        }
    }
    ll ans=maxn;
    for(int i=1; i<=m; i++) ans=min(ans,dp[n][i][k]);
    if(ans>=maxn)printf("-1\n");
    else printf("%I64d\n",ans);

    return 0;
}

D. Directed Roads

题解:很水的强连通分量,可以很容易发现对于一个环n,那么破除这个环的总数有(2^N-2)种, 既然时n条边,而且每个点都只有1出度,那么我的想法就是只要破除了环,就可以了,假设有M个点,N个点为环最后答案为2^M *(2^N-2) 用乘法原理解决了 .
ps:如果我没卡上面那题就好了…

/* Author:GavinjouElephant
 * Title:
 * Number:
 * main meanning:
 *
 *
 *
 */


#include <iostream>
using namespace std;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <vector>
#include <set>
#include <cstdlib>
#include <map>
#include <queue>
//#include<initializer_list>
//#include <windows.h>
//#include <fstream>
//#include <conio.h>
#define MaxN 0x7fffffff
#define MinN -0x7fffffff
#define lson 2*k
#define rson 2*k+1
typedef long long ll;
const int INF=0x3f3f3f3f;
const int maxn=2e5+10;
const ll mod=1e9+7;
int Scan()//读入整数外挂.
{
    int res = 0, ch, flag = 0;

    if((ch = getchar()) == '-')             //判断正负
        flag = 1;

    else if(ch >= '0' && ch <= '9')           //得到完整的数
        res = ch - '0';
    while((ch = getchar()) >= '0' && ch <= '9' )
        res = res * 10 + ch - '0';
    return flag ? -res : res;
}
 void Out(int a)    //输出外挂
 {
     if(a>9)
         Out(a/10);
     putchar(a%10+'0');
 }

 int V;
 vector<int> G[maxn];
 vector<int> rG[maxn];
 vector<int> vs;

 bool used[maxn];
 int cmp[maxn];
 int cnt_cmp[maxn];
 int Sum;
 void add_edge(int from ,int to)
 {
     G[from].push_back(to);
     rG[to].push_back(from);
 }

 void dfs(int v)
 {
     used[v]=true;
     for(int i=0;i<G[v].size();i++)
     {
         if(!used[G[v][i]]) dfs(G[v][i]);
     }
     vs.push_back(v);
 }

 void rdfs(int v,int k)
 {
     Sum++;
     used[v]=true;
     cmp[v]=k;
     for(int i=0;i<rG[v].size();i++)
     {
         if(!used[rG[v][i]]) rdfs(rG[v][i],k);
     }
 }

 int scc()
 {
     memset(used,0,sizeof(used));
     vs.clear();
     for(int v=0;v<V;v++)
     {
         if(!used[v]) dfs(v);
     }
     memset(used,0,sizeof(used));

     int k=0;

     for(int i=vs.size()-1;i>=0;i--)
     {

         if(!used[vs[i]])
         {
             Sum=0;
             rdfs(vs[i],k);
             cnt_cmp[k++]=Sum;
         }
     }
     return k;
 }
 ll qmod(ll a,ll n)
 {
     ll res=1;
     while(n)
     {
         if(n&1)res=(res*a)%mod;
         a=(a*a)%mod;
         n>>=1;
     }
     return res%mod;
 }
 ll qmul(ll a,ll n)
 {
      ll res=0;
      while(n)
      {
          if(n&1)res=(res+a)%mod;
          a=(a+a)%mod;
          n>>=1;
      }
      return res%mod;

 }
int main()
{
#ifndef ONLINE_JUDGE
    freopen("coco.txt","r",stdin);
    freopen("lala.txt","w",stdout);
#endif
     int to;
     scanf("%d",&V);
     for(int i=0;i<V;i++)
     {
         scanf("%d",&to);
         to--;
         add_edge(i,to);
     }

     int K=scc();
     ll ans=1;
     for(int i=0;i<K;i++)
     {
         if(cnt_cmp[i]>1)
         {
             ll tmp=(qmod(2,(ll)cnt_cmp[i])-2+mod)%mod;
             ans=qmul(ans,tmp);
         }
         else  ans=qmul(ans,2)%mod;
     }
     printf("%I64d\n",ans);

    return 0;
}

E. ZS and The Birthday Paradox

分析:
转载:http://blog.csdn.net/acmore_xiong/article/details/52409248
这个讲得很清楚,我也不懂这个数论的知识,我看了才明白的.

/* Author:GavinjouElephant
 * Title:
 * Number:
 * main meanning:
 *
 *
 *
 */


#include <iostream>
using namespace std;
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <sstream>
#include <cctype>
#include <vector>
#include <set>
#include <cstdlib>
#include <map>
#include <queue>
//#include<initializer_list>
//#include <windows.h>
//#include <fstream>
//#include <conio.h>
#define MaxN 0x7fffffff
#define MinN -0x7fffffff
#define lson 2*k
#define rson 2*k+1
typedef long long ll;
const int INF=0x3f3f3f3f;
const ll mod=1e6+3;
int Scan()//读入整数外挂.
{
    int res = 0, ch, flag = 0;

    if((ch = getchar()) == '-')             //判断正负
        flag = 1;

    else if(ch >= '0' && ch <= '9')           //得到完整的数
        res = ch - '0';
    while((ch = getchar()) >= '0' && ch <= '9' )
        res = res * 10 + ch - '0';
    return flag ? -res : res;
}
 void Out(int a)    //输出外挂
 {
     if(a>9)
         Out(a/10);
     putchar(a%10+'0');
 }
 ll n,k;
 ll qmod(ll a,ll b,ll MOD)
 {
      ll ret=1;
      while(b)
      {
          if(b&1)ret=(ret*a)%mod;
          a=(a*a)%mod;
          b>>=1;
      }
      return ret;
 }
int main()
{
#ifndef ONLINE_JUDGE
    freopen("coco.txt","r",stdin);
    freopen("lala.txt","w",stdout);
#endif

    scanf("%I64d%I64d",&n,&k);

    if(n<64&&(k>((1ll)<<n)))
    {
        printf("1 1\n");
        return 0;
    }
    ll t=0;
    for(ll i=2;i<=(k-1);i<<=1)
    {
        t+=(k-1)/i;
    }
    ll gcd=qmod(2,t,mod);
    ll x=qmod(2,n,mod);
    ll A,B;
    A=B=1;
    for(ll i=1;i<=(k-1);i++)
    {
        A=A*(x-i+mod)%mod;
        if(!A)break;
    }
    ll inv=qmod(gcd,mod-2,mod);

    A=A*inv%mod;
    B=qmod(x,k-1,mod);
    B=B*inv%mod;
    A=(B-A+mod)%mod;
    printf("%I64d %I64d\n",A,B);



    return 0;
}

内容概要:本文围绕“光伏-储能-数据中心”系统的容量优化配置展开研究,旨在通过构建数学模型并结合Matlab编程实现,对园区内光伏发电、储能设备与数据中心算力负荷之间的多能互补关系进行协同优化。研究综合考虑可再生能源出力的波动性、储能系统的充放电特性以及数据中心的动态用电需求与算力调度特性,建立以最小化综合成本、降低碳排放强度、提升能源自给率等为目标的多目标优化模型,并采用先进的智能优化算法(如粒子群、灰狼、鲸鱼等)进行求解,从而确定光伏装机容量与储能系统配置的最优方案。文中提供了完整的Matlab代码实现流程,涵盖数据预处理、模型构建、算法求解与结果可视化全过程,属于综合能源系统与信息基础设施深度融合的前沿交叉课。; 适合人群:具备电力系统、能源工程、自动化或计算机等相关专业背景,熟悉Matlab编程与基本优化算法原理,从事新能源利用、绿色数据中心、综合能源系统规划与低碳调度等方向的研究生、科研人员及工程技术人员。; 使用场景及目标:① 掌握光伏-储能-数据中心耦合系统的建模思路与多能流协同机制;② 学习基于Matlab的多目标容量优化配置方法与智能算法应用技巧;③ 为工业园区、数字经济园区及绿色数据中心的能源系统规划、节能减排与可持续运行提供科学决策依据和技术解决方案。; 阅读建议:建议结合所提供的Matlab代码,深入理解目标函数设计、约束条件设定及算法实现细节,可通过调整负荷参数、改变气候数据、引入新的优化目标或约束条件等方式进行拓展性实验,以深化对系统特性的认知并提升实际科研与工程应用能力。
内容概要:本文档聚焦于“考虑源网荷储协调的主动配电网优化调度方法”的Matlab代码复现研究,属于电力系统与综合能源系统领域的高水平科研资源。文档系统阐述了融合电源侧、电网侧、负荷侧及储能系统(源-网-荷-储)协同优化的主动配电网调度模型,旨在通过先进的数学优化方法提升电力系统的经济性、可靠性与低碳化水平。研究内容涵盖多时间尺度调度架构、不确定性建模(如新能源出力波动)、鲁棒优化或分布鲁棒优化(DRO)等核心技术,并依托Matlab平台完成模型构建与仿真验证。同时,文档列举了多个前沿研究方向,如光储充一体化、主从博弈、微电网双层优化、电氢耦合系统、电动汽车集群调度等,体现出其在现代智能电网与综合能源系统优化调度中的代表性与前瞻性。; 适合人群:具备电力系统基础理论知识和Matlab编程能力,从事能源、电气工程、自动化、可再生能源等方向研究的研究生、科研人员及工程技术人员,特别适合致力于优化建模、智能算法应用与综合能源系统仿真的研究人员。; 使用场景及目标:① 复现高水平期刊论文中的主动配电网优化调度模型;② 掌握源网荷储协同优化的建模方法与Matlab实现技术;③ 借助所提供的完整代码资源开展二次开发、算法改进或新场景拓展,服务于科研创新、项目申报与学术论文撰写。; 阅读建议:建议结合文档中提及的相关文献与案例,按照目录结构循序渐进地学习,重点理解模型构建的逻辑框架与代码实现的关键细节,并利用附带的百度网盘资源获取全部代码与数据文件,通过动手实践加深对优化算法与工程应用的理解。
内容概要:本文围绕《考虑光伏-储能-数据中心多能互补的园区容量优化配置(Matlab代码实现)》这一技术资源,系统研究了工业园区内光伏发电、储能系统与数据中心之间的能量协同与容量优化问。通过构建融合可再生能源出力不确定性、负荷波动及数据中心算力负荷特性的数学优化模型,采用Matlab编程实现多能互补系统的容量配置求解,旨在提升能源利用效率、降低运营成本与碳排放,并增强园区能源系统的稳定性与经济性。文中综合运用分布鲁棒机会约束(DRCC)、N-1安全准则、鲁棒优化等先进建模方法,确保方案在复杂运行环境下的可行性与可靠性,适用于综合能源系统(IES)的规划与调度研究。; 适合人群:面向具备电力系统、能源系统或优化算法基础的研究生、科研人员及工程技术人员,尤其适合熟悉Matlab编程及YALMIP、CPLEX等优化工具的专业人士;对于从事智慧园区、绿色数据中心或低碳能源系统研究的人员亦具有较高参考价值。; 使用场景及目标:①支撑科研项目中对含数据中心的智慧园区进行多能互补建模与仿真分析;②用于撰写学位论文、期刊投稿中的案例验证与算法对比;③指导实际工程中光伏与储能容量的科学规划与配置决策;④深入学习分布鲁棒优化、N-1安全约束等高级方法在能源系统中的集成应用。; 阅读建议:建议结合提供的Matlab代码逐模块解析模型实现过程,重点关注目标函数构建、约束条件设定及求解器接口调用逻辑。推荐对照“顶级EI复现”案例,掌握工业级建模规范,并尝试复现关键结果以加深理解。同时可延伸学习文中关联的多时间尺度调度与协同优化策略,全面提升综合能源系统的研究与实践能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值