您的位置:首页 > 其它

Codeforces #265 Div 1 简要题解

2015-06-24 16:16 627 查看

A. No to Palindromes!

题目链接

http://codeforces.com/contest/464/problem/A

题目大意

给你一个字符串SS,其中不包含任何长度大于等于2的回文子串,要你找一个长度和SS相同,且字典序比SS大字典序最小的S′S',使得S′S'也不包含任何长度大于等于2的回文子串

思路

显然S′S'的前缀是和SS相同的,而二者的后缀则不同。假设二者不相同的后缀对应于区间[t,|S|][t,|S|]。我们首先要找出最大的tt,使得第tt位修改后,S′S'的[1,t][1,t]部分不含任何长度大于等于2的回文串。在确定下来tt之后,我们再向后把[t+1,|S|][t+1,|S|]这部分都确定下来。

由于SS本身已经保证不包含任何长度大于等于2的回文子串,因此,在SSS上修改第xx位字符,只要保证第xx位字符不会构成新的长度为2或3的回文子串即可(也就是第xx位和第x−1,x−2,x+1,x+2x-1,x-2,x+1,x+2位不相同)。由于我们这里是从左往右确定S′S'的字符,因此在考虑第xx位时,第x+1,x+2...x+1,x+2...位还没确定下来,因此只要保证第xx位和第x−1,x−2x-1,x-2位不相同就行了

代码

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>

#define MAXN 1100

using namespace std;

char s[MAXN],original[MAXN];
int n,p,num[MAXN];

char Find(int pos)
{
for(char ch=s[pos]+1;ch<='a'+p-1;ch++)
{
if((pos>=2&&ch==s[pos-1])||(pos>=3&&ch==s[pos-2])) continue;
else return ch;
}
return 0;
}

bool solve()
{
int L=-1;
for(int i=n;i>=1;i--)
{
char tmp=Find(i);
if(tmp)
{
s[i]=tmp;
L=i;
break;
}
}
if(L==-1) return false;
for(int i=L+1;i<=n;i++)
{
s[i]='a'-1;
char tmp=Find(i);
if(tmp) s[i]=tmp;
}
return true;
}

int main()
{
scanf("%d%d",&n,&p);
scanf("%s",s+1);
for(int i=1;i<=n;i++) original[i]=s[i];
if(!solve()) printf("NO\n");
else printf("%s",s+1);
return 0;
}


B. Restore Cube

题目链接

http://codeforces.com/contest/464/problem/B

题目大意

给你八个点的坐标(xi,yi,zi)(x_i,y_i,z_i),要你对这八个点的坐标的x,y,zx,y,z重新排列,使得新的八个点构成一个立方体。输出一种方案,无解输出NO

思路

本次比赛最水的题,不过还是很卡细节的

直接DFS枚举八个点的排列情况即可。每次枚举完之后,进行八次判定。第ii次判定固定点ii,求出点1,2...81,2...8到点ii的七个距离。若这八个点可以构成立方体,则其中三个距离为aa,另外有三个距离2√a\sqrt 2 a,另外还有一个距离3√a\sqrt 3 a

代码

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>

#define MAXN 10

using namespace std;

typedef long long int LL;

struct Point
{
LL x,y,z;
Point(){}
Point(LL _x,LL _y,LL _z):x(_x),y(_y),z(_z){}
}points[10];

LL dist(Point a,Point b)
{
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z);
}

LL dis[10];
int top=0;

bool check(int p)
{
top=0;
for(int i=1;i<=8;i++)
if(i!=p) dis[++top]=dist(points[p],points[i]);
sort(dis+1,dis+top+1);
if(dis[1]==0) return false;
if(dis[1]!=dis[2]||dis[1]!=dis[3]) return false;
if(dis[4]!=dis[5]||dis[4]!=dis[6]) return false;
if(dis[1]*2!=dis[4]||dis[1]*3!=dis[7]) return false;
return true;
}

void DFS(int pos)
{
if(pos>8)
{
bool flag=true;
for(int i=1;i<=8;i++)
if(!check(i))
{
flag=false;
break;
}
if(flag)
{
printf("YES\n");
for(int i=1;i<=8;i++)
printf("%I64d %I64d %I64d\n",points[i].x,points[i].y,points[i].z);
exit(0);
}
return;
}
Point tmp=points[pos];
DFS(pos+1);

points[pos]=Point(tmp.x,tmp.z,tmp.y);
DFS(pos+1);

points[pos]=Point(tmp.y,tmp.x,tmp.z);
DFS(pos+1);

points[pos]=Point(tmp.y,tmp.z,tmp.x);
DFS(pos+1);

points[pos]=Point(tmp.z,tmp.x,tmp.y);
DFS(pos+1);

points[pos]=Point(tmp.z,tmp.y,tmp.x);
DFS(pos+1);
}

int main()
{
for(int i=1;i<=8;i++)
scanf("%I64d%I64d%I64d",&points[i].x,&points[i].y,&points[i].z);
DFS(1);
printf("NO\n");
return 0;
}


C. Substitutes in Number

题目链接

http://codeforces.com/contest/464/problem/C

题目大意

给你一个数字SS,qq次将其中的所有的数位t(0≤t≤9)t(0\leq t\leq 9)替换成一个数字(这个数字可能大于10),或者删去所有的这样的数位。问最终这个数字mod109+7\mod 10^9+7的值是多少

思路

因为最后要输出的答案是要取模的,很容易想到这个题和数学、DP有关系。

如果正序来回答所有询问的话,每次取了模之后,之后的询问显然就做不了了,因此需要离线倒序解决询问。从nn到1枚举第tt个询问,维护val[i]=val[i]=数位ii在t+1t+1到nn号操作后的取模的值,length[i]=length[i]=数位ii在t+1t+1到nn号操作后的数字长度(注:长度若是ll,则length[i]=10lmod109+7length[i]=10^l\mod 10^9+7)。

若第tt个询问是将数位xx变成了数字ss,我们可以很容易地用所有的val[i],length[i]val[i],length[i]代换出val[x]val[x]。最后我们再用所有的val[i],length[i]val[i],length[i]代换出SS的值即可

代码

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <string>

#define MOD 1000000007
#define MAXN 110000

using namespace std;

typedef long long int LL;

LL fastPow(LL base,LL pow)
{
LL ans=1;
while(pow)
{
if(pow&1) ans=ans*base%MOD;
base=base*base%MOD;
pow>>=1;
}
return ans;
}

LL pow[MAXN];
char s[MAXN],tmp[MAXN];
int n,q;

struct Operate
{
int x;
string s;
}opt[MAXN];

LL length[12]; //length[i]=经过了t~n号操作后,数字i变成的新数字的长度(用10^i mod p表示)
LL val[12]; //val[i]=经过了t~n号操作后,数字i变成的新数字的取模后的值

int main()
{
scanf("%s",s);
n=strlen(s);
scanf("%d",&q);
for(int i=1;i<=q;i++)
{
scanf("%d->",&opt[i].x);
gets(tmp);
opt[i].s=tmp;
}
for(int i=0;i<=9;i++)
{
val[i]=i;
length[i]=10;
}
for(int t=q;t>=1;t--)
{
LL len=opt[t].s.length();
if(!len)
{
val[opt[t].x]=0;
length[opt[t].x]=1;
continue;
}
LL now=0,nowlen=1; //now=t~q号操作后,数字opt[t].x变成的数字取模的值,nowlen=t~q号操作后,数字opt[t].x变成的数字长度(10^i mod p表示)
for(int i=0;i<len;i++)
{
now=now*length[opt[t].s[i]-'0']%MOD;
now=(now+val[opt[t].s[i]-'0'])%MOD;
nowlen=(nowlen*length[opt[t].s[i]-'0'])%MOD;
}
val[opt[t].x]=now;
length[opt[t].x]=nowlen;
}
int len=strlen(s);
LL now=0; //now=1~q号操作后,初始数字变成的数字取模的值
for(int i=0;i<len;i++)
{
now=now*length[s[i]-'0']%MOD;
now=(now+val[s[i]-'0'])%MOD;
}
printf("%I64d\n",now);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: