Codeforces Round #369 (Div. 2) 套题

A:模拟水题不说

#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <bitset>

using namespace std;
typedef long long LL;
const int N= 1e3+5;
char s[N][10];
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;++i)scanf("%s",s[i]+1);
      bool flag=false;
    for(int i=1;i<=n;++i){
      if(s[i][1]==s[i][2]&&s[i][1]=='O'){
         flag=true;
         s[i][1]=s[i][2]='+';
         break;
      }
      if(s[i][4]==s[i][5]&&s[i][4]=='O'){
         flag=true;
         s[i][4]=s[i][5]='+';
         break;
      }
    }
    if(flag)printf("YES
");
    else printf("NO
");
    if(flag)
      for(int i=1;i<=n;++i)printf("%s
",s[i]+1);
    return 0;
}
View Code

B:n*n的方阵,只有一个位置是未填数的,然后问填数以后,行和列和主副对角线和相等
     O(n^2)模拟即可(这题FST了,由于输出格式不太对,对了这个也许能上更多分吧)

#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <bitset>

using namespace std;
typedef long long LL;
const int N= 5e2+5;
LL a[N][N]; 
int main(){
    int n,x,y;
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
      for(int j=1;j<=n;++j){
        scanf("%I64d",&a[i][j]);
        if(a[i][j]==0){
          x=i;
          y=j;
        }
      }
    }
    if(n==1){
      printf("1
");
      return 0;
    }
    LL sum=0;
    if(x==1)
      for(int i=1;i<=n;++i)sum+=a[2][i];
    else
      for(int i=1;i<=n;++i)sum+=a[1][i];
    LL ret=-1;
    for(int i=1;i<=n;++i){
      LL tmp=0;
      for(int j=1;j<=n;++j)
        tmp+=a[i][j];
      if(i==x){
        if(tmp<sum){
          if(ret!=-1&&ret!=sum-tmp){
            printf("-1
");
            return 0;
          }
          else ret=sum-tmp;
        }
        else {
          printf("-1
");
          return 0;
        }
      }
      else{
        if(sum!=tmp){
          printf("-1
");
          return 0;
        }
      }    
    }
    for(int j=1;j<=n;++j){
      LL tmp=0;
      for(int i=1;i<=n;++i)
        tmp+=a[i][j];
      if(j==y){
        if(tmp<sum){
          if(ret!=-1&&ret!=sum-tmp){
            printf("-1
");
            return 0;
          }
          else ret=sum-tmp;
        }
        else {
          printf("-1
");
          return 0;
        }
      }
      else{
        if(sum!=tmp){
          printf("-1
");
          return 0;
        }
      }    
    }
    LL tmp=0;
    for(int i=1;i<=n;++i)tmp+=a[i][i];
    if(x==y){
      if(tmp<sum){
          if(ret!=-1&&ret!=sum-tmp){
            printf("-1
");
            return 0;
          }
          else ret=sum-tmp;
        }
        else {
          printf("-1
");
          return 0;
        }
    }
     else{
        if(sum!=tmp){
          printf("-1
");
          return 0;
        }
      }
    tmp=0;
    for(int i=1;i<=n;++i)tmp+=a[i][n+1-i];
      if(x+y==n+1){
      if(tmp<sum){
          if(ret!=-1&&ret!=sum-tmp){
            printf("-1
");
            return 0;
          }
          else ret=sum-tmp;
        }
        else {
          printf("-1
");
          return 0;
        }
    }
     else{
        if(sum!=tmp){
          printf("-1
");
          return 0;
        }
      }
      printf("%I64d
",ret);       
    return 0;
}
View Code

C:赛场上写了个裸的O(n^4)的dp,dp[i][j][k]代表当前是第i个数,这个数是j,分成k块的最小值
    由于是时限是2s,而且是CF评测机,不虚

#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <bitset>

using namespace std;
typedef long long LL;
const int N= 1e2+5;
LL dp[N][N][N];
LL p[N][N];
int a[N];
int main(){
  int n,m,k;
  scanf("%d%d%d",&n,&m,&k);
  for(int i=1;i<=n;++i)scanf("%d",&a[i]);
  for(int i=1;i<=n;++i){
    for(int j=1;j<=m;++j)
     scanf("%I64d",&p[i][j]);
  }
  memset(dp,-1,sizeof(dp));
  if(a[1]!=0)dp[1][a[1]][1]=0;
  else{
    for(int i=1;i<=m;++i)
      dp[1][i][1]=p[1][i];
  }
  for(int i=2;i<=n;++i){
    int lim=min(k,i);
    if(a[i]!=0){
      for(int j=1;j<=lim;++j){
        for(int c=1;c<=m;++c){
          if(dp[i-1][c][j-1]!=-1&&a[i]!=c){
            if(dp[i][a[i]][j]==-1)dp[i][a[i]][j]=dp[i-1][c][j-1];
            else dp[i][a[i]][j]=min(dp[i][a[i]][j],dp[i-1][c][j-1]);
          }
          if(dp[i-1][c][j]!=-1&&a[i]==c)
            if(dp[i][a[i]][j]==-1)dp[i][a[i]][j]=dp[i-1][c][j];
            else dp[i][a[i]][j]=min(dp[i][a[i]][j],dp[i-1][c][j]);
        }
      }
      continue;
    }
    for(int x=1;x<=m;++x){
      for(int j=1;j<=lim;++j){
        for(int c=1;c<=m;++c){
          if(dp[i-1][c][j-1]!=-1&&x!=c){
            if(dp[i][x][j]==-1)dp[i][x][j]=dp[i-1][c][j-1]+p[i][x];
            else dp[i][x][j]=min(dp[i][x][j],dp[i-1][c][j-1]+p[i][x]);
          }
          if(dp[i-1][c][j]!=-1&&x==c)
            if(dp[i][x][j]==-1)dp[i][x][j]=dp[i-1][c][j]+p[i][x];
            else dp[i][x][j]=min(dp[i][x][j],dp[i-1][c][j]+p[i][x]);
        }
      }
    }
  }
  LL ret=-1;
  for(int i=1;i<=m;++i)
    if(dp[n][i][k]!=-1){
      if(ret==-1)ret=dp[n][i][k];
      else ret=min(ret,dp[n][i][k]);
    }
  printf("%I64d
",ret);
  return 0;
}
View Code

D:这种题很常见,有向环套树,看每个环的反转方案,是2^k-2(k是边数,必须翻一个,不能全翻)
     剩下的树上的边翻不翻都可以是2^tot,tot代表树边,然后都乘起来即可

#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <bitset>
using namespace std;
typedef long long LL;
const int N = 2e5+5;
const LL mod = 1e9+7;
int to[N],n;
int vis[N];
LL qpow(LL x,LL y){
  LL ret=1;
  while(y){
    if(y&1)ret=ret*x%mod;
    y>>=1;
    x=x*x%mod;
  }
  return ret;
} 
int main(){
  scanf("%d",&n);
  for(int i=1;i<=n;++i)scanf("%d",&to[i]);
  LL z=n,ret=1;
  for(int i=1;i<=n;++i){
    if(vis[i])continue;
    int x=i;
    while(!vis[x]){
      vis[x]=i;
      x=to[x];
    }
    if(vis[x]!=i)continue;
    int t=x,cnt=0;
    do{
      ++cnt;
      t=to[t];
    }while(t!=x);
    z-=cnt;
    ret=1ll*ret*((qpow(2,cnt)-2+mod)%mod)%mod;
  }
  ret=ret*qpow(2,z)%mod;
  printf("%I64d
",ret);
  return 0;
}
View Code

E:考虑正难则反,概率等于1-A(k,2^n)/2^(nk),然后发现最大公约数只能是2^i,约分即可

#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <math.h>
#include <bitset>
using namespace std;
typedef long long LL;
const int N = 2e5+5;
const LL mod = 1e6+3;
LL qpow(LL x,LL y){
  LL ret=1;
  while(y){
    if(y&1)ret=ret*x%mod;
    x=x*x%mod;y>>=1;
  }
  return ret;
}
int main(){
  LL n,k;
  scanf("%I64d%I64d",&n,&k);
  if(n<=62&&k>1ll<<n){
    printf("1 1
");
    return 0;
  }
  LL num=0;
  for(LL i=k-1;i;i>>=1){
    num+=i/2;
  }
  LL b=1,a=qpow(2,n);
  for(LL i=1;i<=k-1;++i){
    LL tmp=(a-i+mod)%mod;
    b=b*tmp%mod;
    if(tmp==0)break; 
  }
  LL inv=qpow(qpow(2,num),mod-2);
  a=qpow(a,k-1);
  a=a*inv%mod;
  b=b*inv%mod;
  b=(a-b+mod)%mod;
  printf("%I64d %I64d
",b,a);
  return 0;
}
View Code
原文地址:https://www.cnblogs.com/shuguangzw/p/5822256.html