Codeforces Round #324 (Div. 2) (584A,584B(排列组合),584C(构造),584D(哥德巴赫猜想),584E(置换群))

1.Olesya and Rodion


题目链接:

http://codeforces.com/problemset/problem/584/A

解题思路:

Two cases: t = 10 and t ≠ 10.

If t = 10 then there are two cases again :). If n = 1 then answer is  - 1 (because there is not any digit divisible by t). If n > 1, then answer, for example, is '1111...110' (contains n - 1 ones).

If t < 10 then answer, for example, is 'tttttttt' (it, obviously, divisible by t).

题目大意:

给你二个数n、t,求一个能够被t整除的n位数,存在多组解时输出任意一组,不存在时输出“-1”。

AC代码:

#include <bits/stdc++.h>
using namespace std;

int main(){
    int n,t;
    while(~scanf("%d%d",&n,&t)){
        if(t == 10){
            if(n == 1)
                printf("-1\n");
            else{
                n--;
                for(int i = 0; i < n; i++)
                    printf("1");
                printf("0\n");
            }
        }
        else{
            for(int i = 0; i < n; i++)
                printf("%d",t);
            printf("\n");
        }
    }
    return 0;
}

2.Kolya and Tanya(排列组合)


题目链接:

http://codeforces.com/problemset/problem/584/B

解题思路:

The number of ways to choose ai (without any conditions) — 33n. Let A be the number of ways to choose ai with condition that in every triangle gnomes have 6 coins. Then answer is 33n - A.

Note that we can separate all gnomes on n independent triangles (i-th triangle contains of aiai + nai + 2ni < n). So we can count answer for one triangle and then multiply the results. To count answer for one triangle, we can note that there are 7 ways to choose gnomes with 6coins (all permutations 123 and 222).

So answer is — 33n - 7n. We count it in O(n).

题目大意:

在一个圆上,3n个点依次标号,然后标号为i,i+n,i+2n的点连成三角形。然后每个点分配一个值(在1-3范围内)。然后只要有一个

三角形的点的值的和不为6就成功。问有多少种分配方案。

算法思想:

排列组合。总共3^3n个可能,减去7^n个不可能的结果。因为要么是222要么是123才能有6,然后222只有1种123可以6种,加起来

一个三角形的不成功的情况有7种。

AC代码:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int mod = 1e9+7;

ll pow_mod(ll base,int n){
    ll ans = 1;
    while(n){
        if(n&1)
            ans = (ans*base)%mod;
        base = (base*base)%mod;
        n >>= 1;
    }
    return ans;
}

int main(){
    int n;
    while(~scanf("%d",&n)){
        printf("%lld\n",(pow_mod(27LL,n)-pow_mod(7LL,n)+mod)%mod);
    }
    return 0;
}

3.Marina and Vasya(构造)


题目链接:

http://codeforces.com/problemset/problem/584/C

解题思路:

Let's find a string that will be equal to s1 in k = n - t positions and equal to s2 in k = n - t positions. Let's denote q = quantity of i thats1i = s2i. If k ≤ q, then let's take k positions such that s1pos = s2pos and put in answer the same symbols. Then put in other n - k positions symbols, which are not equal to corresponding in s1 and s2 (we can do it, because we have 26 letters).

Now k > q. So, if there is an answer, where exists pos such that s1pos = s2poss1pos ≠ anspos, let's denote ansi = s1i, and then in any position such that s1i ≠ s2i = ansi and s1i = ansi (and in the same position in s2) we will choose ai, such that ai ≠ s1i and ai ≠ s2i (we can do it because k > q). So, for every position from q we can put symbols, equal to corresponding symbols in s1 and s2. Now we have strings s1, s2 of length n - q (such that s1i ≠ s2i for every i) and we should find string ans such that f(ans, s1) = f(ans, s2). We know thats1i ≠ s2i, so ansi may be equal to corresponding in s1 or to corresponding in s2 or not equal to s1i and to s2i. So, we need, at least,2(k - q) symbols in answer to make f(s1, ans) = k - q and f(s2, ans) = k - q. Consequently, if n - q < 2(k - q), the answer is  - 1, and else just put first k - q symbols in answer from s1, next k - q symbols from s2, and others won't be equal to corresponding in s1 and s2.

Solution works in O(n).

题目大意:

给你两个长度为n的串a、b,然后要你找出一个新串c,这个串c和之前两个串不同的字符数目恰好为t个。

算法思想:

反过来想,令same为g(a,c),先找a[i],b[i]两个串相同的位置并标记,相同的个数为cnt,如果same > cnt+(n-cnt)/2,则不能同时满

足g(a,c)=same,g(a,c)=same。所以输出-1即可。然后先使c[i]满足a[i]=b[i]的情况。接着再满足c[i]=a[i]和c[i]=b[i]的情况,剩下的全是

不相等的情况,一一枚举即可。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

char a[100005],b[100005],c[100005];
int vis[100005];

int main(){
    int n,t;
    while(~scanf("%d%d",&n,&t)){
        memset(c,0,sizeof(c));
        memset(vis,0,sizeof(vis));
        scanf("%s",a);
        scanf("%s",b);
        int flag = 0,same = n-t,cnt = 0;
        for(int i = 0; i < n; i++){
            if(a[i] == b[i]){
                vis[i] = 1;
                cnt++;
            }
        }
        if(same > cnt+(n-cnt)/2){
            printf("-1\n");
            continue;
        }
        for(int i = 0; i < n; i++){
            if(same && vis[i]){
                c[i] = a[i];
                same--;
            }
        }
        cnt = same;
        for(int i = 0; i < n; i++){
            if(cnt && !c[i]){
                c[i] = a[i];
                cnt--;
            }
        }
        cnt = same;
        for(int i = 0; i < n; i++){
            if(cnt && !c[i]){
                c[i] = b[i];
                cnt--;
            }
        }
        for(int i = 0; i < n; i++){
            if(!c[i]){
                for(char j = 'a';; j++){
                    if(j != a[i] && j != b[i]){
                        c[i] = j;
                        break;
                    }
                }
            }
        }
        c[n] = '\0';
        printf("%s\n",c);
    }
    return 0;
}

4.Dima and Lisa(哥德巴赫猜想)


题目链接:

http://codeforces.com/problemset/problem/584/D

解题思路:

There is a fact that the distance between adjacent prime numbers isn't big. For n = 109 maximal distanse is 282. So let's find maximal prime p, such that p < n - 1 (we can just decrease n while it's not prime(we can check it in )). We know that n - p < 300. Now we have even (because n and p are odd) number n - p and we should divide it into a sum of two primes. As n - p < 300, we can just iterate over small primes P and check if P is prime and n - p - P is prime. You can check that there is a solution for all even numbers less than300 by bruteforce.

题目大意:

给你一个数n,要你把n拆成1-3个素数的和。n是奇数。

算法思想:

哥德巴赫猜想:任一大于2的偶数都可写成两个质数之和。

AC代码:

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;

bool is_prime(int n){
    int tmp = sqrt(n*1.0);
    for(int i = 2; i <= tmp; i++)
        if(n%i == 0)
            return false;
    return n > 1? true: false;
}

int main(){
    int n;
    scanf("%d",&n);
    if(is_prime(n))
        printf("1\n%d\n",n);
    else if(is_prime(n-2))
        printf("2\n2 %d\n",n-2);
    else{
        n -= 3;
        for(int i = 2; ; i++){
            if(is_prime(i) && is_prime(n-i)){
                printf("3\n3 %d %d\n",i,n-i);
                break;
            }
        }
    }
    return 0;
}

5.Anton and Ira(置换群)


题目链接:

http://codeforces.com/problemset/problem/584/E

解题思路:

We can consider that we pay 2|i - j| coins for swap (we can divide answer in the end). Then we can consider that we pay |i - j| coins for moving pi and |i - j| for moving pj. So, if x was on position i and then came to position j, then we will pay at least |i - j| coins. Then the answer is at least  (pp — position k in permutation p, and ps — position k in permutation s). Let's prove that this is the answer by showing the algorithm of making swaps.

Let's consider that permutation s is sorted (our task is equal to it). Then we will put numbers from n to 1 on their positions.

How we can put n on its position? Denote ppos = n. Let's prove that there exists a position pos2 such that pos < pos2 andppos2 ≤ pos(then we will swap ppos2 with n (and both numbers will move to their final positions and n will move to the right, so we can repeat this process until n returns to its position)). We can note that there are only n - pos positions that are bigger than pos. And how many numbers on these positions can be bigger than pos? We can say that answer is n - pos, but it's incorrect, because n is bigger thanpos, but posn ≤ pos. Now we can use Pigeonhole principle and say that position x, such that x > pos and px ≤ pos exists.

But now our algorithm is O(n3). How we can put n in its position in O(n) operations? Let's move the pointer to the right while number is bigger than pos. Then swap n with found number. After we can move pointer from new n's position, so pointer always moves to the right and will not do more then n steps.

题目大意:

给你一个1-n的排列,让你通过交换i,j变成另外一个1-n的排列,交换的代价为abs(i-j)。问你最小代价,然后输出交换的步骤。

AC代码:

#include <bits/stdc++.h>
using namespace std;

typedef pair<int,int> P;

const int N = 2005;
int a[N];
int b[N];
int pos1[N];
int pos2[N];
vector<P> res;
vector<P>::iterator it;

int main(){
    int n;
    scanf("%d",&n);
    for(int i = 1; i <= n; i++)
        scanf("%d",&a[i]);
    for(int i = 1; i <= n; i++){
        scanf("%d",&b[i]);
        pos1[b[i]] = i;
    }
    int ans = 0;
    for(int i = 1; i <= n; i++){
        a[i] = pos1[a[i]];
        pos2[a[i]] = i;
    }
    for(int num = n; num >= 1; num--){
        int pos = pos2[num];
        if(pos == num)
            continue;
        for(int i = pos; i <= num; i++){
            if(a[i] <= pos){
                ans += i - pos;
                swap(pos2[a[i]], pos2[a[pos]]);
                swap(a[i], a[pos]);
                res.push_back(P{i, pos});
                pos = i;
            }
        }
    }
    printf("%d\n",ans);
    printf("%d\n",res.size());
    for(it = res.begin(); it != res.end(); it++)
        printf("%d %d\n", (*it).first, (*it).second);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值