【第22期】观点:IT 行业加班,到底有没有价值?

Codeforces Round #369 (Div. 2) A~D

原创 2016年08月30日 23:51:37

前言:这场又蹦了。。。还是老老实实补题吧。
A:水题就不说了

#include<bits/stdc++.h>
#define rep(i,a,n) for (int i=a;i<n;i++)
using namespace std;
string s[1010];
int main(){
    int n;
    while(cin>>n){
        int ans=0;
        rep(i,0,n){
           cin>>s[i];
           if(!ans){
            if(s[i][0]=='O'&&s[i][1]=='O'){
              s[i][0]='+';s[i][1]='+';
              ans=1;
            }
            else if(s[i][3]=='O'&&s[i][4]=='O'){
              s[i][3]='+';s[i][4]='+';
              ans=1;
            }
           }
        }
        if(!ans) cout<<"NO"<<endl;
        else{
            cout<<"YES"<<endl;
            rep(i,0,n) cout<<s[i]<<endl;
        }
    }
}

B:
题意:n*n矩阵 里,有一个位置是0,待你填入一个大于0的数,使得矩阵每行,每列,两对角线之和相等,输出可能存在的这个数,不存在输出-1.

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[800][800];
int n;
bool check(int x,int y,ll v){
   a[x][y]=v;
   ll ans=0,sum=0;
   for(int i=1;i<=n;i++) ans+=a[1][i];
   for(int i=1;i<=n;i++){
       sum=0;
       for(int j=1;j<=n;j++) sum+=a[i][j];
       if(sum!=ans) return false;
   }
   for(int i=1;i<=n;i++){
      sum=0;
      for(int j=1;j<=n;j++) sum+=a[j][i];
      if(sum!=ans) return false;
   }
   sum=0;
   for(int i=1;i<=n;i++) sum+=a[i][i];
   if(sum!=ans) return false;
   sum=0;
   for(int i=1;i<=n;i++) sum+=a[i][n+1-i];
   if(sum!=ans) return false;
   return true;
}

int main(){
    while(~scanf("%d",&n)){
        int x,y;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                cin>>a[i][j];
                if(a[i][j]==0) {x=i;y=j;}
            }
        }
        if(n==1){
            cout<<10<<endl;
            continue;
        }
        ll sum=0,ans=0;
        int p=1;
        while(x==p) p++;
        for(int i=1;i<=n;i++){
            sum+=a[x][i];
            ans+=a[p][i];
        }
        if(check(x,y,ans-sum)&&ans-sum>0) cout<<ans-sum<<endl;
        else cout<<-1<<endl;
    }
}

C:
题意:有n个数的序列,多少个不相同的连续序列的个数是他的美丽度。比如 :1 2 2 1 美丽度是3 ,{1} {2,2} {1}三个不相同的连续序列。
同时每个位置可能预先被选定一个颜色,0表示没有选定。同时给出每个位置用哪个颜色(数字)代价是不同的,问整个串美丽度为k的最消耗费是?
思路:典型区间dp问题。设dp[i][j][k]表示:选到第i个数,美丽度为j的情况下选择k的颜色的最小耗费。
我的做法O(n^4) n<=100
那么详细的转移方程见代码 :

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf=0x7fffffffffff;
ll dp[110][110][110],cost[110][110],c[110];
int main(){
   int N,M,K;
   while(~scanf("%d%d%d",&N,&M,&K)){
      for(int i=1;i<=N;i++) scanf("%I64d",&c[i]);
      for(int i=1;i<=N;i++){
        for(int j=1;j<=M;j++){
           scanf("%I64d",&cost[i][j]);
        }
      }
      for(int i=0;i<=N;i++){
        for(int j=0;j<=K;j++){
           for(int k=0;k<=M;k++){
              dp[i][j][k]=inf;
           }
        }
      }
      if(c[1]==0){
        for(int i=1;i<=M;i++) dp[1][1][i]=cost[1][i];
      }
      else{
        dp[1][1][c[1]]=0;
      }
      for(int i=2;i<=N;i++){
         for(int j=1;j<=K;j++){
             if(c[i]==0){
                for(int k=1;k<=M;k++){
                    for(int l=1;l<=M;l++){
                        if(k!=l) dp[i][j][k]=min(dp[i][j][k],dp[i-1][j-1][l]+cost[i][k]);
                        else  dp[i][j][k]=min(dp[i][j][k],dp[i-1][j][k]+cost[i][k]);
                    }
                }
             }
             else{
                for(int k=1;k<=M;k++){
                    if(k!=c[i]) dp[i][j][c[i]]=min(dp[i][j][c[i]],dp[i-1][j-1][k]);
                    else dp[i][j][c[i]]=min(dp[i][j][c[i]],dp[i-1][j][c[i]]);
                }
             }
         }
      }
      ll ans=inf;
      for(int i=1;i<=M;i++) ans=min(ans,dp[N][K][i]);
      if(ans>=inf) printf("-1\n");
      else printf("%I64d\n",ans);
   }
}

D:
题意:
给出一个n个节点n条边的有向图,可以把一条边反向,现在问有多少种方式可以使这个图没有自循环的环;
思路:可以发现一共n个边,对于一个环来说,随便反转哪些边就可以,不过有两种不行就是都不反转和都反转,假设这个环有s条边,那么就有2^s-2种方式,其他不在环里的边sum可以反转可以不反转;
所以答案:(2^s-2)*2^sum
具体找每个环内有多少边,和总工有多少边在 环里,一个dfs就好。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2*100000+10;
const ll mod=1e9+7;
int a[N],vis[N],dep[N],sum=0;
ll ans;
ll pow_mod(ll a,ll n){
    ll as=1;
    ll tmp=a%mod;
    while(n){
        if(n&1) as=(as*tmp)%mod;
        tmp=tmp*tmp%mod;
        n>>=1;
    }
    return as;
}

int dfs(int cur,int deep,int fa){
    vis[cur]=fa;
    dep[cur]=deep;
    if(!vis[a[cur]]) dfs(a[cur],deep+1,fa);
    else if(vis[a[cur]]==fa){
        ans=ans*(pow_mod(2,dep[cur]-dep[a[cur]]+1)-2+mod)%mod;
        sum+=dep[cur]-dep[a[cur]]+1;
    }
}

int main(){
    int n;
    while(~scanf("%d",&n)){
       ans=1;sum=0;
       memset(vis,0,sizeof(vis));
       for(int i=1;i<=n;i++) scanf("%d",&a[i]);
       for(int i=1;i<=n;i++) if(!vis[i]) dfs(i,0,i);
       ans=ans*pow_mod(2,n-sum)%mod;
       printf("%I64d\n",ans);
    }
}
版权声明:朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。 举报

相关文章推荐

Codeforces Round #369 (Div2) ABCDE

比赛链接:Codeforces Round 369 (Div2) A: 暴力B: 暴力C: dp,可以暴力,也可以不暴力D: 拓扑排序,dfs,方案计数E: 数学,待续A. Bus to Udayl...

[Codeforces Round #369 (Div. 2)D. Directed Roads]Tarjan强连通分量+组合计数

[Codeforces Round #369 (Div. 2)D. Directed Roads]Tarjan强连通分量题目链接:[Codeforces Round #369 (Div. 2)D. D...

程序员升职加薪指南!还缺一个“证”!

CSDN出品,立即查看!

Codeforces Round #369 (Div. 2) D. Directed Roads 图论、组合学、二重dfs、并查集形式的图、Interesting、好题

图论、组合学、 二重dfs、并查集形式的图、Interesting、好题 可以把图分成两部分, 另一部分是链状的 方案数是 2^k次(k条边), 一部分是很多的环((C m, 1) + (C m, 2...

[Codeforces Round #369 (Div. 2) C. Coloring Trees] DP

[Codeforces Round #369 (Div. 2) C. Coloring Trees] DP题目链接:[Codeforces Round #369 (Div. 2) C. Colorin...

Codeforces Round #369 (Div. 2) A~D

A. Bus to Udayland time limit per test 2 seconds memory limit per test 256 megabytes input sta...
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)