Codeforces Round #191 (Div.2) 题解

    • A
    • B
    • C
    • D
    • E

这场打的很爽,题目质量很高.

A

给一个01序列,能将一个子串取反,求整个序列的最多1的个数.
数据范围很小,暴力枚举所有子串取反,求最大的值即可.

#include //Ithea Myse Valgulious
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rec register char
#define rel register ll
#define gc getchar
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
inline int read(){
  int x=0,f=1;char c=gc();
  for (;!isdigit(c);c=gc()) f^=c=='-';
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return f?x:-x;
  }
template <typename mitsuha>
inline bool read(mitsuha &x){
  x=0;int f=1;char c=gc();
  for (;!isdigit(c)&&~c;c=gc()) f^=c=='-';
  if (!~c) return 0;
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return x=f?x:-x,1;
  }
template <typename mitsuha>
inline int write(mitsuha x){
  if (!x) return 0&pc(48);
  if (x<0) x=-x,pc('-');
  int bit[20],i,p=0;
  for (;x;x/=10) bit[++p]=x%10;
  for (i=p;i;--i) pc(bit[i]+48);
  return 0;
  }
inline char fuhao(){
  char c=gc();
  for (;isspace(c);c=gc());
  return c;
  }
}using namespace chtholly;
using namespace std;
int a[999],n,b[999];

int main(){
scanf("%d",&n);
for (int i=1;i<=n;++i) a[i]=read();
int ans=0;
for (int i=1;i<=n;++i){
  for (int j=i;j<=n;++j){
    int tmp=0;
    memcpy(b,a,sizeof b);
    for (int k=i;k<=j;++k) b[k]=!b[k];
    for (int k=1;k<=n;++k) tmp+=b[k];
    ans=max(ans,tmp);
    }
  }write(ans);
}

B

让你构造一个长度为n,严格递增,前面的数不能整除后面的数的序列.
很容易想到构造质数数列.输出前 n n 个质数即可.

#include //Ithea Myse Valgulious
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rec register char
#define rel register ll
#define gc getchar
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
inline int read(){
  int x=0,f=1;char c=gc();
  for (;!isdigit(c);c=gc()) f^=c=='-';
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return f?x:-x;
  }
template <typename mitsuha>
inline bool read(mitsuha &x){
  x=0;int f=1;char c=gc();
  for (;!isdigit(c)&&~c;c=gc()) f^=c=='-';
  if (!~c) return 0;
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return x=f?x:-x,1;
  }
template <typename mitsuha>
inline int write(mitsuha x){
  if (!x) return 0&pc(48);
  if (x<0) x=-x,pc('-');
  int bit[20],i,p=0;
  for (;x;x/=10) bit[++p]=x%10;
  for (i=p;i;--i) pc(bit[i]+48);
  return 0;
  }
inline char fuhao(){
  char c=gc();
  for (;isspace(c);c=gc());
  return c;
  }
}using namespace chtholly;
using namespace std;
const int mulu=2e6;
int p[mulu|10]={1,1},pr[mulu|10];

void pre(){
int i,j;
for (i=2;i<=mulu;++i) if (!p[i]){
  pr[++pr[0]]=i;
  for (j=i<<1;j<=mulu;j+=i) p[j]=1;
  }
}

int main(){
int n=read();
pre();
for (int i=1;i<=n;++i) write(pr[i]),p32;
}

C

给出一个数字,将它重复k次,可以去掉一些数字使它变成5的倍数,可以有前导0.
问有多少种去掉的方法,mod 1e9+7.

对于每一位的5 5 0 0 ,它前面的数字都可以随便取.
所以每一位的5 5 0 0 都可以构造出一个等比数列求和,稍微推一下公式用快速幂搞定.

#include //Ithea Myse Valgulious
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rec register char
#define rel register ll
#define gc getchar
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
inline int read(){
  int x=0,f=1;char c=gc();
  for (;!isdigit(c);c=gc()) f^=c=='-';
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return f?x:-x;
  }
template <typename mitsuha>
inline bool read(mitsuha &x){
  x=0;int f=1;char c=gc();
  for (;!isdigit(c)&&~c;c=gc()) f^=c=='-';
  if (!~c) return 0;
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return x=f?x:-x,1;
  }
template <typename mitsuha>
inline int write(mitsuha x){
  if (!x) return 0&pc(48);
  if (x<0) x=-x,pc('-');
  int bit[20],i,p=0;
  for (;x;x/=10) bit[++p]=x%10;
  for (i=p;i;--i) pc(bit[i]+48);
  return 0;
  }
inline char fuhao(){
  char c=gc();
  for (;isspace(c);c=gc());
  return c;
  }
}using namespace chtholly;
using namespace std;
const int yuzu=1e5,mod=1e9+7;
char c[yuzu|10];

ll kasumi(ll a,ll b){
ll s=1;
for (;b;b>>=1,a=a*a%mod) if (b&1) s=s*a%mod;
return s;
}

int main(){
scanf("%s",c+1);
int k=read(),i,j,len=strlen(c+1),cnt=0;
ll ans=0;
int inv=kasumi(kasumi(2,len)-1,mod-2);
for (j=1;j<=len;++j){
  if (c[j]=='0'||c[j]=='5'){
    ans=(ans+(kasumi(2,j+1ll*k*len-1)-kasumi(2,j-1)+mod)*inv%mod+mod)%mod;
    }
  }write(ans);
}

D

一个方格图中有一些障碍物.你可以执行3种操作:
1.在空地上建一个蓝色房子;
2.在蓝色房子的旁边建一个红色房子.
3.推倒一座房子.
红色房子的价值是蓝色房子的两倍.
给你地图,在1e6步以内构造出一种建造方法使得造出房子的总价值最大.

很明显每一个连通块里只留一座蓝色房子,剩下的都建红色房子.
那么只要先全建上蓝色房子,按照建造顺序倒回去推倒重建红色房子即可.

#include //Ithea Myse Valgulious
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rec register char
#define rel register ll
#define gc getchar
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
inline int read(){
  int x=0,f=1;char c=gc();
  for (;!isdigit(c);c=gc()) f^=c=='-';
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return f?x:-x;
  }
template <typename mitsuha>
inline bool read(mitsuha &x){
  x=0;int f=1;char c=gc();
  for (;!isdigit(c)&&~c;c=gc()) f^=c=='-';
  if (!~c) return 0;
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return x=f?x:-x,1;
  }
template <typename mitsuha>
inline int write(mitsuha x){
  if (!x) return 0&pc(48);
  if (x<0) x=-x,pc('-');
  int bit[20],i,p=0;
  for (;x;x/=10) bit[++p]=x%10;
  for (i=p;i;--i) pc(bit[i]+48);
  return 0;
  }
inline char fuhao(){
  char c=gc();
  for (;isspace(c);c=gc());
  return c;
  }
}using namespace chtholly;
using namespace std;
const int yuzu=1e6,d[]={1,0,-1,0,0,1,0,-1};
int n=read(),m=read(),vis[505][505];
char c[505][505];

#define yi first
#define er second
typedef pair<int,int> node;

int k;
struct ans{
int x,y;char op;
}llx[yuzu|10];

void bfs(int sx,int sy,int last){
queue q;
vis[sx][sy]=1;
q.push(node(sx,sy));
llx[++k]={sx,sy,'B'};
for (;!q.empty();){
  node u=q.front();q.pop();
  for (int i=0;i<4;++i){
    int nx=u.yi+d[i],ny=u.er+d[i+4];
    if (nx>0&&ny>0&&nx<=n&&ny<=m&&c[nx][ny]^'#'&&!vis[nx][ny]){
      q.push(node(nx,ny));
      llx[++k]={nx,ny,'B'};
      vis[nx][ny]=1;
      }
    }
  }
int i,now=k;
for (i=now;i>last+1;--i){
  llx[++k]={llx[i].x,llx[i].y,'D'};
  llx[++k]={llx[i].x,llx[i].y,'R'};
  }
}

int main(){
int i,j;
for (i=1;i<=n;++i) scanf("%s",c[i]+1);
for (i=1;i<=n;++i){
  for (j=1;j<=m;++j){
    if (c[i][j]^'#'&&!vis[i][j]) bfs(i,j,k);
    }
  }
cout<for (i=1;i<=k;++i){
  printf("%c %d %d\n",llx[i].op,llx[i].x,llx[i].y);
  }
}

E

给出一串数字和至多两个不幸运的数字,求该串数字有多少个排列没有一个前缀和等于某个不幸运的数字.
折半枚举?不存在的!状压瞎搞!
dp[i]=dp[ilowbit(i)]+dp[lowbit(i)] d p [ i ] = d p [ i − l o w b i t ( i ) ] + d p [ l o w b i t ( i ) ]

#include //Ithea Myse Valgulious
using namespace std;
const int mulu=1<<24,mod=1e9+7;
int dp[mulu],a[mulu];
#define lowbit(x) (x&-x)
int r[2]={-1,-1};
int main(){
int i,j,n,k;
scanf("%d",&n);
for (i=0;iscanf("%d",&dp[1<for (scanf("%d",&k),i=0;iscanf("%d",&r[i]);
for (a[0]=1,i=1;i<(1<if ((i^lowbit(i))&&(dp[i]=dp[i^lowbit(i)]+dp[lowbit(i)])>mod) dp[i]=mod;
  if (dp[i]^r[0]&&dp[i]^r[1]){
    for (j=i;j;j-=lowbit(j)){//枚举每一个子集进行转移.
      a[i]+=a[i^lowbit(j)];
      if (a[i]>=mod) a[i]-=mod;
      }
    }
  }printf("%d\n",a[(1<1]);
}

你可能感兴趣的:(codeforces,总结,题解,codeforces,总结,题解)