Codeforces #265 Div 1 简要题解

A. No to Palindromes!

题目链接

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的回文子串,因此,在SS上修改第 x 位字符,只要保证第x位字符不会构成新的长度为2或3的回文子串即可(也就是第 x 位和第x1,x2,x+1,x+2位不相同)。由于我们这里是从左往右确定 S 的字符,因此在考虑第 x 位时,第x+1,x+2...位还没确定下来,因此只要保证第 x 位和第x1,x2位不相同就行了

代码

#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,y,z 重新排列,使得新的八个点构成一个立方体。输出一种方案,无解输出NO

思路

本次比赛最水的题,不过还是很卡细节的
直接DFS枚举八个点的排列情况即可。每次枚举完之后,进行八次判定。第 i 次判定固定点i,求出点 1,2...8 到点 i 的七个距离。若这八个点可以构成立方体,则其中三个距离为a,另外有三个距离 2a ,另外还有一个距离 3a

代码

#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

题目大意

给你一个数字 S q次将其中的所有的数位 t(0t9) 替换成一个数字(这个数字可能大于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 <script type="math/tex" id="MathJax-Element-2102">S</script>的值即可

代码

#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值