天天看点

Codeforces Round #265(div2)题解

比赛的时候没有注意策略,绕过C去做D结果姿势不对D题还TLE了,害得C可以做的也没做

后来补题发现E应该也是可以做的=_=,原本可以紫的一场啊...

( 465A ) Problem A . inc ARG 

题目大意:

就是现在倒着给了一个二进制数,现在在权值最低的那位上加1问得到的结果会有几位发生数字变化,不用考虑全部是1然后最后多一位的那位

代码如下:

Result  :  Accepted     Memory  :  8 KB     Time  : 31 ms

/*
 * Author: Gatevin
 * Created Time:  2014/9/7 23:24:52
 * File Name: A.cpp
 */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;

int n;
int a[110];


int main()
{
    cin>>n;
    for(int i = 1; i <= n; i++)
    {
        scanf("%1d", &a[i]);
    }
    int cnt = 0;
    int now = 1;
    while(now <= n && a[now] == 1)
    {
        cnt++;
        now++;
    }
    if(now <= n && a[now] == 0)
    {
        cnt++;
    }
    cout<<cnt<<endl;
    return 0;
}
           

( 465B ) Problem B . Inbox(100500)

题目大意:

就是判连续的1的组数乘上2减1...算贪心么?

注意没有1的时候是0

代码如下:

Result  : Accepted     Memory  :  8 KB     Time  :  31 ms

/*
 * Author: Gatevin
 * Created Time:  2014/9/7 23:37:48
 * File Name: A.cpp
 */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;

int n;
int a[1010];

int main()
{
   cin>>n;
   for(int i = 1; i <= n; i++)
   {
       cin>>a[i];
   }
   int now = 1;
   int answer = 0;
   while(now <= n)
   {
       if(a[now] == 0) now++;
       else
       {
           while(a[now] == 1)
           {
               now++;
               answer++;
           }
           answer++;
       }
   }
   if(answer)
   {
        cout<<answer - 1<<endl;
   }
   else
   {
       cout<<0<<endl;
   }
    return 0;
}
           

( 464A ) Problem C . No to Palindromes

题目大意:

给出n和p,然后是一个满足条件的串s, 问是否存在一个长度为n的字符串,其只包含前p个字母('a' ~ 'a' + p - 1),并且该字符串的任意字串都不是回文串,存在就输出字典序比s打的串中字典序最小的那个

大致思路:

首先可以发现对于长度为2的串两个字符不能相等,长度为3的串头和尾不能相等,这样不难发现,当p大于等于3时,对于位置 i 的字符只要与前两个位置的字符不同,就可以构造一个满足条件的串,当p = 1或者 p = 2时容易特判

接下来可以从给出的串的最后一位开始枚举是否是从那个位置开始改变,然后按照下一个字符和其前两个不同来构造字典序最小的串即可,就是一个贪心

代码如下:

Result  :  Accepted     Memory  :  12 KB     Time  :  31 ms

/*
 * Author: Gatevin
 * Created Time:  2014/9/8 10:56:01
 * File Name: A.cpp
 */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;

int n,p;
string s;

bool check(int x)
{
    if(x >= 2)
    {
        for(int i = 1; s[x] + i <= 'a' + p - 1; i++)
        {
            if(s[x] + i != s[x - 1] && s[x] + i != s[x - 2])
            {
                s[x] = s[x] + i;
                return true;
            }
        }
        return false;
    }
    if(x == 0)
    {
        if(s[x] + 1 <= 'a' + p - 1)
        {
            s[x] = s[x] + 1;
            return true;
        }
        else
        {
            return false;
        }
    }
    if(x == 1)
    {
        for(int i = 1; s[x] + i <= 'a' + p - 1; i++)
        {
            if(s[x] + i != s[x - 1])
            {
                s[x] = s[x] + i;
                return true;
            }
        }
        return false;
    }
}



int main()
{
    cin>>n>>p;
    cin>>s;
    if(p == 1)
    {
        printf("NO\n");
        return 0;
    }
    if(p == 2)
    {
        if(n == 1)
        {
            if(s == "a") printf("b\n");
            else printf("NO\n");
            return 0;
        }
        if(n == 2)
        {
            if(s == "ab") printf("ba\n");
            else printf("NO\n");
            return 0;
        }
    }   
    unsigned int tmp = s.length();
    for(unsigned int i = s.length() - 1; i <= s.length() - 1; i--)
    {
        if(check(i))//是否从位置i开始改变
        {
            tmp = i;
            break;
        }
    }
    if(tmp == s.length())//没有找到满足条件的位置i
    {
        printf("NO\n");
        return 0;
    }
    tmp++;
    while(tmp <= s.length())
    {
        if(tmp == 1)//之前从第一位开始改变的
        {
            for(char i = 'a'; i <= 'a' + p - 1; i++)//从位置tmp开始向后构造满足条件的字典序最小的串
            {
                if(i != s[tmp - 1])
                {
                    s[tmp] = i;
                    tmp++;
                    break;
                }
            }
        }
        else
        {
            for(char i = 'a'; i <= 'a' + p - 1; i++)
            {
                if(i != s[tmp - 1] && i != s[tmp - 2])
                {
                    s[tmp] = i;
                    tmp++;
                    break;
                }
            }
        }
    }
    cout<<s<<endl;
    return 0;
}
           

( 464B ) Problem D . Restore Cube

题目大意:

依次给出8个三维坐标,现在每个坐标自己的x,y,z位置可以互换,问是否可以互换使得最终这8个点能成为一个正方体的8个顶点

大致思路:

首先暴力枚举可能的排列情况有6^9大约165万种情况

然后对于每一种排列判断是否是正方体的8个顶点

我判断的方法是求出8个点的中心到8个点的距离是否相等,然后这样可以知道8个点在一个球上,其中心是球心

这里在取一个顶点判断到另外7个顶点的距离中最小数的出现次数,如果是3则可以

(注意判断点重合的情况)

代码如下:

Result  :  Accepted     Memory  :  4 KB     Time  :  249 ms

/*
 * Author: Gatevin
 * Created Time:  2014/9/8 8:40:49
 * File Name: B.cpp
 */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;

struct point
{
    int x,y,z;
    point(){}
    point(int _x, int _y, int _z) : x(_x), y(_y), z(_z){}
    void input()
    {
        scanf("%d %d %d", &x, &y, &z);
    }
    void output()
    {
        printf("%d %d %d\n", x, y, z);
    }
};

bool operator == (const point & p1, const point & p2)
{
    return p1.x == p2.x && p1.y == p2.y && p1.z == p2.z;
}


point all[8][6];
int test[8];
point p[8];
bool flag;

void check()
{
    for(int i = 0; i < 8; i++) p[i] = all[i][test[i]];
    for(int i = 0; i < 8; i++)//判断点的重合
    {
        for(int j = i + 1; j < 8; j++)
        {
            if(p[i] == p[j]) return;
        }
    }
    lint sx = 0, sy = 0, sz = 0;
    for(int i = 0; i < 8; i++)
    {
        sx = sx + (lint)p[i].x; sy = sy + (lint)p[i].y; sz = sz + (lint)p[i].z;
    }
    lint tmp = (sx - 8*(lint)p[0].x)*(sx - 8*(lint)p[0].x) + (sy - 8*(lint)p[0].y)*(sy - 8*(lint)p[0].y) + (sz - 8*(lint)p[0].z)*(sz - 8*(lint)p[0].z);
    lint tmp2;
    for(int i = 1; i < 8; i++)//判断8个点到中心的距离是否相等
    {
        tmp2 = (sx - 8*(lint)p[i].x)*(sx - 8*(lint)p[i].x) + (sy - 8*(lint)p[i].y)*(sy - 8*(lint)p[i].y) + (sz - 8*(lint)p[i].z)*(sz - 8*(lint)p[i].z);
        if(tmp2 != tmp) return;
    }
    int cnt = 0;
    lint minn = 1e15;
    for(int i = 1; i < 8; i++)//计算另外7个点到这个点的距离中最小值出现的次数
    {
        lint tmp = ((lint)p[i].x - (lint)p[0].x)*((lint)p[i].x - (lint)p[0].x) + ((lint)p[i].y - (lint)p[0].y)*((lint)p[i].y - (lint)p[0].y) + ((lint)p[i].z - (lint)p[0].z)*((lint)p[i].z - (lint)p[0].z);
        if(tmp == minn)
        {
            cnt++;
        }
        else
        {
            if(tmp < minn)
            {
                cnt = 1;
                minn = tmp;
            }
        }
    }
    if(cnt != 3) return;
    else
    {
        flag = true;
    }
    return;
}



void dfs(int deep)//枚举可能的组合
{
    if(deep == 8)
    {
        if(!flag)//当前还没有找到答案过
        check();
        return;
    }
    for(int j = 0; j < 6; j++)
    {
        test[deep] = j;
        dfs(deep + 1);
    }
    return;
}

int main()
{
    flag = false;
    for(int i = 0; i < 8; i++)
    {
        all[i][0].input();
        all[i][1].x = all[i][0].x; all[i][1].y = all[i][0].z; all[i][1].z = all[i][0].y;
        all[i][2].x = all[i][0].y; all[i][2].y = all[i][0].x; all[i][2].z = all[i][0].z;
        all[i][3].x = all[i][0].z; all[i][3].y = all[i][0].y; all[i][3].z = all[i][0].x;
        all[i][4].x = all[i][0].y; all[i][4].y = all[i][0].z; all[i][4].z = all[i][0].x;
        all[i][5].x = all[i][0].z; all[i][5].y = all[i][0].x; all[i][5].z = all[i][0].y;
    }
    dfs(0);
    if(!flag) printf("NO\n");
    else
    {
        printf("YES\n");
        for(unsigned int i = 0; i < 8; i++)
        {
            p[i].output();
        }
    }
    return 0;
}
           

( 464C ) Problem E . Substitutes in Number

题目大意:

先给出长度不超过10^5的串s只包含 0 ~ 9 , 然后是n次操作 (n <= 10^5), 每次将其中一个数更换成一串数,求最后得到的数对10^9 + 7 取模的结果

大致思路:

首先对于每一个数,后面的操作将会影响前面的结果,现在我们倒着来,从最后一个开始,每次更新一个数代表的字符串

用val [ i ] 代表数字 i 在更新之后代表的数字

用wei [ i ] 代表当前在一个串后面加上数字 i 前面的整体需要乘上的倍数

那么每次从后往前更新当前的val [ 0 ~ 9 ] 和wei [ 0 ~ 9 ] ,最终 val[ 0 ~ 9 ]将是原串对应数字的值,wei [ i ] 为在后面添加字符 i 之后前面需要乘上的倍数

这些需要自己意会,详见代码

Result  :  Accepted     Memory  :  3528 KB     Time  :  62 ms

/*
 * Author: Gatevin
 * Created Time:  2014/9/8 15:46:00
 * File Name: A.cpp
 */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;

const lint mod = 1000000007LL;

struct change//变更方案
{
    int num;
    string s;
};

change C[100010];
lint val[10];
lint wei[10];
char buf[100010];
string all;
int n;

int main()
{
    cin>>all;
    cin>>n;
    getchar();
    for(int i = 1; i <= n; i++)
    {
        scanf("%d->", &C[i].num);
        gets(buf);
        C[i].s = buf;
    }
    for(int i = 0; i < 10; i++)
    {
        val[i] = i;
        wei[i] = 10LL;
    }
    for(int i = n ; i >= 1; i--)
    {
        if(C[i].s == "")
        {
            wei[C[i].num] = 1;
            val[C[i].num] = 0;
            continue;
        }
        lint tmp1 = 1LL;
        lint tmp2 = 0LL;
        for(unsigned int j = 0; j < C[i].s.length(); j++)
        {
            tmp2 = (tmp2 * wei[C[i].s[j] - '0']) % mod;
            tmp2 = (tmp2 + val[C[i].s[j] - '0']) % mod;
            tmp1 = (tmp1 * wei[C[i].s[j] - '0']) % mod;
        }
        wei[C[i].num] = tmp1;
        val[C[i].num] = tmp2;
    }
    lint ans = 0LL;
    for(unsigned int i = 0; i < all.length(); i++)
    {
        ans = (ans * wei[all[i] - '0']) % mod;
        ans = (ans + val[all[i] - '0']) % mod;
    }
    cout<<ans<<endl;
    return 0;
}