#codeforces #369 div2

全场wa longlong 无颜见江东父老

a题

找两个连着的O变成+

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int n;
char s[1010][5];
void init(){
    scanf("%d",&n);
    int flag = 0;
    for(int i = 0 ; i < n ;i++){
        scanf("%s",s[i]);
       // printf("%s\n",s[i]);
        if(s[i][0] == 'O' &&s[i][1] == 'O'&&flag == 0)
            s[i][0] = '+',s[i][1] = '+',flag = 1;
        else if(s[i][3] == 'O' &&s[i][4] == 'O'&&flag == 0)
            s[i][3] = '+',s[i][4] = '+',flag = 1;
    }
    if(flag){
        printf("YES\n");
        for(int i = 0 ; i < n;i++){
            for(int j = 0 ; j < 5 ;j++)
                printf("%c",s[i][j]);
            printf("\n");
        }
    }

    else{
        printf("NO\n");
    }

}

int main(){
    init();
}

b题:

把0的位置填数字,使得每行没列主对角线和副对角线的和都相同,做不到输出-1

wa点:

首先wa4 如果只有一个数字,不是0的话就不变,是零输出1或者随便什么数字
wa7 这个数字0 wa94 这个数字<0
血粼粼的教训

我是用行判断ans,填数字,在判断填入后列和对角线的条件是否符合

#include<cstdio>
#include <iostream>
#include <cstring>
#define maxn 520
using namespace std;
int n,anr,anl;
long long r[maxn],l,flag,ans;
long long a[maxn][maxn];
int init(){
    for(int i = 0 ; i < n ;i++){
        flag = 0;
        for(int j = 0 ; j < n ;j++){
            scanf("%I64d",&a[i][j]);
            if(a[i][j] == 0)
                anr = i,anl = j,flag = 1;
            r[i]+=a[i][j];
        }
        if(flag == 0&&ans == 0)
            ans = r[i];
        if(ans != 0 && ans != r[i]&&flag == 0)
            return -1;
    }
}

void sov(){
    a[anr][anl] = ans-r[anr];
    for(int j = 0 ; j < n ;j++){
        l = 0;
        for(int i = 0 ; i < n ;i++){
            l += a[i][j];
        }
        if(l != ans){
            printf("-1\n");
            return;
        }
    }
    long long lp = 0;
    for(int i = 0 ; i < n ; i++){
        lp += a[i][i];
       // cout << lp <<endl;
    }
    if(lp != ans){
        printf("-1\n");
        return;
    }
    lp = 0;
    for(int i = 0 ; i < n ;i++)
        lp += a[i][n-1-i];
    if(lp != ans){
        printf("-1\n");
        return ;
    }
    if(a[anr][anl]>0)
        printf("%I64d\n",a[anr][anl]);
    else
        printf("-1\n");
}

int main(){
    scanf("%d",&n);
    if(n == 1){
        int aa = 0;
        scanf("%d",&aa);
        if(aa == 0)
            printf("1\n");
        else
            printf("%d\n",aa);
    }
    else{
        if(init() == -1)
            printf("-1\n");
        else
            sov();
    }

}

c题:

比赛的时候就剩下20分钟,看了一眼,直接无脑开三维(最后一维可以滚动,没时间改了),dp【i】【j】【k】表示当前第 i 课树,涂第 j 种颜色,已经分了 k 块颜色,要知道k只可能是前一个棵树的k或者+1,不解释了,转移要分一下,这棵树如果有颜色就不存在j了,直接给corlor【i】,else 和前一棵树颜色一样与否,循环前一棵树的第二帷 ,O(n^4),有点暴力哈

#include <cstdio>
#include <iostream>
#define maxn 110
using namespace std;
int n,m,k;
long long dp[maxn][maxn][maxn],a[maxn][maxn],cl[maxn];

void init(){
    scanf("%d%d%d",&n,&m,&k);
    for(int i = 1 ; i <= n ;i++)
        scanf("%I64d",&cl[i]);
    for(int i = 1 ; i <= n ;i++)
        for(int j = 1; j <= m ;j++)
            scanf("%I64d",&a[i][j]);
    for(int i = 0 ; i <= n ; i++)
        for(int j = 0 ; j <= m ; j++)
            for(int l = 0 ; l <= k ;l++)
                dp[i][j][l] = 1e15;

    for(int i = 0 ; i <= m ;i++){
         if(k == 1)
            dp[0][i][1] = 0;
         dp[0][i][0] = 0;
    }
}

void sov(){
    for(int i = 1 ; i <= n ;i++){
        for(int j = 1 ; j <= m ;j++){
            for(int nn = 1 ;nn <= k ;nn++){
                if(cl[i] != 0)
                    for(int jj =1; jj <= m ;jj++)
                        if(jj != cl[i])
                            dp[i][cl[i]][nn] = min(dp[i][cl[i]][nn],dp[i-1][jj][nn-1]);
                        else
                            dp[i][cl[i]][nn] = min(dp[i-1][jj][nn],dp[i][cl[i]][nn]);
                else{
                   for(int jj =1 ; jj <= m ;jj++)
                        if(jj != j)
                            dp[i][j][nn] = min(dp[i][j][nn],dp[i-1][jj][nn-1]+a[i][j]);
                        else{
                             dp[i][j][nn] = min(dp[i][j][nn],dp[i-1][jj][nn]+a[i][j]);
                             // printf("dp [ %d ] [ %d ] [ %d ] = %d \n",i,j,nn,dp[i][j][nn]);
                        }
                }
            }
        }

    }
  //  cout << dp[1][1][1]<<endl;
    long long ans = 1e15;
    for(int i = 1 ; i <= m ;i++){
        ans = min(ans,dp[n][i][k]);
        //cout << n <<i << k <<dp[n][i][k] <<endl;
    }
    if(ans >= 1e15)
        printf("-1\n");
    else
        printf("%I64d\n",ans);
}

int main(){
    init();
    sov();
}

D题:

每个点只有唯一出度,连向另一个点(连自己特判),改变任意条边的方向,使得整个图没有环
因为唯一出度,所以只要你沿着一条线走,如果没遇到某个点,那么这两个点必然不可能在一个环里,环里的随便翻 除了都反转或者都不 就是2^n-2种 外面的随便,剩下多少点就2^n,所以的相乘。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#define maxn 200010
const int mod= 1e9+7;
using namespace std;
vector<int> vc[maxn];
bool vis[maxn],v[maxn];
int n,m,cir,r[maxn],num;
long long ans =1;
int init(){
    scanf("%d",&n);
    for(int i = 1 ; i <= n ;i++){
        int to;
        scanf("%d",&to);
        vc[i].push_back(to);
        if(to == i)
            return -1;
    }
}

long long po(int x){
    long long an = 1;
    for(int i = 0 ; i < x ;i++)
        an = (an*2)%mod;
    return an;
}
int s;
int dfs(int x,int step){

    if(v[x]){
        cir++;
       // cout <<"  "<<step-r[x]<<endl;
        return step-r[x];
    }
    if(vis[x])
        return 0;
    r[x] = step;
    vis[x] =1;
    v[x] = 1;

    for(int i =  0 ; i <vc[x].size();i++){
        s = dfs(vc[x][i],step+1);
    }
    return s;
}

int main(){
   // cout << "ans = "<<ans<<endl;
    if(init() == -1)
        printf("0\n");
    else{
        for(int i = 1; i <= n ;i++){
             if(!vis[i]){
                memset(v,0,sizeof(v));
                 m = dfs(i,0);
                 if(m)
                    ans = (ans*(po(m)-2))%mod;
                  num += m;
             }
        }
        ans = (ans*po(n-num)) %mod;
        printf("%d\n",ans);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值