http://codeforces.com/contest/464/problem/A
给你一个字符串 S ,其中不包含任何长度大于等于2的回文子串,要你找一个长度和 S 相同,且字典序比 S 大的字典序最小的 S′ ,使得 S′ 也不包含任何长度大于等于2的回文子串。
显然 S′ 的前缀是和 S 相同的,而二者的后缀则不同。假设二者不相同的后缀对应于区间 [t,|S|] 。我们首先要找出最大的 t ,使得第 t 位修改后, S′ 的 [1,t] 部分不含任何长度大于等于2的回文串。在确定下来 t 之后,我们再向后把 [t+1,|S|] 这部分都确定下来。
由于 S 本身已经保证不包含任何长度大于等于2的回文子串,因此,在S S 上修改第 x 位字符,只要保证第 x 位字符不会构成新的长度为2或3的回文子串即可(也就是第 x 位和第 x−1,x−2,x+1,x+2 位不相同)。由于我们这里是从左往右确定 S′ 的字符,因此在考虑第 x 位时,第 x+1,x+2... 位还没确定下来,因此只要保证第 x 位和第 x−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;
}
http://codeforces.com/contest/464/problem/B
给你八个点的坐标 (xi,yi,zi) ,要你对这八个点的坐标的 x,y,z 重新排列,使得新的八个点构成一个立方体。输出一种方案,无解输出NO
本次比赛最水的题,不过还是很卡细节的
直接DFS枚举八个点的排列情况即可。每次枚举完之后,进行八次判定。第 i 次判定固定点 i ,求出点 1,2...8 到点 i 的七个距离。若这八个点可以构成立方体,则其中三个距离为 a ,另外有三个距离 2√a ,另外还有一个距离 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;
}
http://codeforces.com/contest/464/problem/C
给你一个数字 S , q 次将其中的所有的数位 t(0≤t≤9) 替换成一个数字(这个数字可能大于10),或者删去所有的这样的数位。问最终这个数字 mod109+7 的值是多少
因为最后要输出的答案是要取模的,很容易想到这个题和数学、DP有关系。
如果正序来回答所有询问的话,每次取了模之后,之后的询问显然就做不了了,因此需要离线倒序解决询问。从 n 到1枚举第 t 个询问,维护 val[i]= 数位 i 在 t+1 到 n 号操作后的取模的值, length[i]= 数位 i 在 t+1 到 n 号操作后的数字长度(注:长度若是 l ,则 length[i]=10lmod109+7 )。
若第 t 个询问是将数位 x 变成了数字 s ,我们可以很容易地用所有的 val[i],length[i] 代换出 val[x] 。最后我们再用所有的 val[i],length[i] 代换出 S 的值即可
#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;
}