Codeforces #265 div1

2015-08-29 18:00:22

传送门

小结:开的VP,这场题目质量很高~比赛中24min过了A题就“吃面包了”。。。

  第二题自己想了个很麻烦的做法... 打不完 - -,赛后补了前3题。

 

A题:技巧,思维。

  题意:给出一个只用前p个小写英文字母的字符串,而且不存在长度>=2的回文子串,让你构造出字典序下一个这样的串(且长度不变)。串长<=1000

  思路:很自然地想到给原来的串不断地+1(在p进制下)然后 n^2 判断是否符合条件,但是这样太慢。有下面更快的判断方法。

    想到如果当前进位到第pos位(设最右位为第一位),1~pos-1位都没发生变化,因此1~pos-1位都不会出现回文。那么我们只需要使得第pos位和第pos-1位以及pos-2位不同即可(不形成长度为2/3的回文),因为如果能形成更长的回文,必须要使得中间部分回文,而前pos-1位并不会出现这样的情况。所以在模拟时先算出涉及进位的最高位,然后补全后面的位,方法如上述。

#include <cstdio>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;

#define getmid(l,r) ((l) + ((r) - (l)) / 2)
#define MP(a,b) make_pair(a,b)
#define PB push_back

typedef long long ll;
typedef pair<int,int> pii;
const double eps = 1e-8;
const int INF = (1 << 30) - 1;

int n,p;
char s[1010];

int main(){
    scanf("%d%d",&n,&p);
    scanf("%s",s + 1);
    int pos = n,c = 1;
    while(pos >= 1){
        s[pos] += c;
        if(s[pos] - 'a' >= p){
            pos--;
            c = 1;
        }
        else{
            if((pos > 1 && s[pos - 1] == s[pos]) || 
                    (pos > 2 && s[pos - 2] == s[pos])){
                c = 1;
            }
            else{
                break;
            }
        }
    }
    if(pos == 0){
        printf("NO\n");
        return 0;
    }
    for(int i = pos + 1; i <= n; ++i){
        bool flag = false;
        for(int j = 0; j < p; ++j){
            s[i] = j + 'a';
            if(i > 1 && s[i - 1] == s[i]) continue;
            if(i > 2 && s[i - 2] == s[i]) continue;
            flag = true;
            break;
        }
        if(!flag){
            printf("NO\n");
            return 0;
        }
    }
    printf("%s\n",s + 1);
    return 0;
}
View Code

 

B题:暴力,技巧。

  题意:给出8个点的三个坐标,每个点的x,y,z是打乱的,让你重排每个点的坐标使得8个点形成边长不为9的立方体。

  思路:貌似也只能暴力... 但是有个技巧:保持第一个点不变,暴力7个点,因为如果把x,y,z轴交换,立方体依旧是立方体。

#include <cstdio>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;

#define getmid(l,r) ((l) + ((r) - (l)) / 2)
#define MP(a,b) make_pair(a,b)
#define PB push_back

typedef long long ll;
typedef pair<int,int> pii;
const double eps = 1e-8;
const int INF = (1 << 30) - 1;

int D[9][4];
int used[10];
bool flag;
int s[9][4];

ll Dis(int a1,int b1,int c1,int a2,int b2,int c2){
    return (ll)(a2 - a1) * (a2 - a1) + (ll)(b2 - b1) * (b2 - b1) + 
        (ll)(c2 - c1) * (c2 - c1);
}

bool Check(){
    ll dis[30];
    int tot = 0;
    for(int i = 1; i <= 8; ++i){
        for(int j = i + 1; j <= 8; ++j){
            dis[++tot] = Dis(s[i][1],s[i][2],s[i][3],s[j][1],s[j][2],s[j][3]);
        }
    }
    sort(dis + 1,dis + 28 + 1);
    if(!dis[1]) return false;
    for(int i = 1; i < 12; ++i) if(dis[i] != dis[i + 1]) return false;
    for(int i = 13; i < 24; ++i) if(dis[i] != dis[i + 1]) return false;
    for(int i = 25; i < 28; ++i) if(dis[i] != dis[i + 1]) return false;
    if(dis[13] != 2 * dis[1] || dis[25] != 3 * dis[1]) return false;
    return true;
}

void Dfs(int p){
    if(flag) return;
    if(p > 7){
        if(Check()){
            flag = true;
            printf("YES\n");
            for(int i = 1; i <= 8; ++i)
                printf("%d %d %d\n",s[i][1],s[i][2],s[i][3]);
        }
        return;
    }
    Dfs(p + 1);
    swap(s[p][1],s[p][2]);
    Dfs(p + 1);
    swap(s[p][2],s[p][3]);
    Dfs(p + 1);
    swap(s[p][1],s[p][2]);
    swap(s[p][2],s[p][3]);
    Dfs(p + 1);
    swap(s[p][2],s[p][3]);
    Dfs(p + 1);
    swap(s[p][2],s[p][3]);
    swap(s[p][1],s[p][2]);
    Dfs(p + 1);
}

int main(){
    for(int i = 1; i <= 8; ++i){
        scanf("%d%d%d",&s[i][1],&s[i][2],&s[i][3]);
    }
    flag = false;
    Dfs(1);
    if(!flag) printf("NO\n");
    return 0;
}
View Code

 

C题:思维。

  题意:对于一个10^5长的串(每一位都是'0'~'9'),每次操作会将1种字母换成1种子串,操作最多10^5个。问最后的答案mod(1e9+7)是几。

  思路:比赛没搞出来... 因为正着想实在是烦,虽然想到保存每个数字最后的值和位数,但是不好算。

    方法是:倒过来进行操作,保存每个数字最后对应的串 mod 之后的值以及其位数。

    (这里算位数是要用于计算10的幂,由于指数很大,可以将指数 mod (1e9+7 - 1) 来加速,原理:指数循环节。当然也可以不用保存位数,而直接保存10的幂。)

#include <cstdio>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;

#define getmid(l,r) ((l) + ((r) - (l)) / 2)
#define MP(a,b) make_pair(a,b)
#define PB push_back

typedef long long ll;
typedef pair<int,int> pii;
const double eps = 1e-8;
const int INF = (1 << 30) - 1;
const int mod = 1e9 + 7;

char s[100010];
string tmp[100010];
int n;
int val[11];
ll len[11];

int Q_pow(int x,int y){
    int ans = 1;
    while(y){
        if(y & 1) ans = 1ll * ans * x % mod;
        x = 1ll * x * x % mod;
        y >>= 1;
    }
    return ans;
}

int main(){
    scanf("%s",s + 1);
    scanf("%d",&n);
    for(int o = 1; o <= n; ++o) cin >> tmp[o];
    for(int i = 0; i < 10; ++i) len[i] = 1,val[i] = i;
    for(int o = n; o >= 1; --o){
        int id = tmp[o][0] - '0';
        int tval = 0;
        ll tlen = 0;
        for(int i = 3; i < tmp[o].size(); ++i){
            int pos = tmp[o][i] - '0';
            tval = (1ll * tval * Q_pow(10,len[pos]) % mod + val[pos]) % mod;
            tlen += len[pos];
        }
        val[id] = tval;
        len[id] = tlen % (mod - 1);
    }
    int ans = 0;
    ll tlen = 0;
    for(int i = 1; s[i]; ++i){
        ans = (1ll * ans * Q_pow(10,len[s[i] - '0']) % mod + val[s[i] - '0']) % mod;
    }
    printf("%d\n",ans);
    return 0;
}
View Code

 

posted @ 2015-08-30 02:46  Naturain  阅读(152)  评论(0编辑  收藏  举报