Codeforces Round #427 (Div. 2) (A-E)(水题 + 贪心 + dp容斥前缀和 + manacher回文串 + 位运算构造)

这场是昨天的校赛,场上只出了两个题,下来后当天补出了C题,今天补完了D E。然后留博客总结。

A. Key races

Two boys decided to compete in text typing on the site "Key races". During the competition, they have to type a text consisting of scharacters. The first participant types one character in v1 milliseconds and has ping t1 milliseconds. The second participant types one character in v2 milliseconds and has ping t2 milliseconds.

If connection ping (delay) is t milliseconds, the competition passes for a participant as follows:

  1. Exactly after t milliseconds after the start of the competition the participant receives the text to be entered.
  2. Right after that he starts to type it.
  3. Exactly t milliseconds after he ends typing all the text, the site receives information about it.

The winner is the participant whose information on the success comes earlier. If the information comes from both participants at the same time, it is considered that there is a draw.

Given the length of the text and the information about participants, determine the result of the game.

Input

The first line contains five integers sv1v2t1t2 (1 ≤ s, v1, v2, t1, t2 ≤ 1000) — the number of characters in the text, the time of typing one character for the first participant, the time of typing one character for the the second participant, the ping of the first participant and the ping of the second participant.

Output

If the first participant wins, print "First". If the second participant wins, print "Second". In case of a draw print "Friendship".

Examples
input
Copy
5 1 2 1 2
output
First

A题:理解加输入输出,其实就是比较v1*s+2*t1 和 v2*s+2*t2的大小,然后直接输出

namespace Solver
{
    void solve()
    {
        int s, v1, v2, t1, t2;
        cin>>s>>v1>>v2>>t1>>t2;
        if(v1*s + 2*t1 < v2*s + 2*t2) puts("First");
        else if(v1*s + 2*t1 > v2*s + 2*t2) puts("Second");
        else puts("Friendship");
    }
};
B. The number on the board

Some natural number was written on the board. Its sum of digits was not less than k. But you were distracted a bit, and someone changed this number to n, replacing some digits with others. It's known that the length of the number didn't change.

You have to find the minimum number of digits in which these two numbers can differ.

Input

The first line contains integer k (1 ≤ k ≤ 109).

The second line contains integer n (1 ≤ n < 10100000).

There are no leading zeros in n. It's guaranteed that this situation is possible.

Output

Print the minimum number of digits in which the initial number and n can differ.

Examples
input
Copy
3
11
output
1

B题:板上有一些数字,加和不小于k。问最少修改几位可以满足。

贪心,每次将最小的修改成最大的造成的影响最大,排序end

namespace Solver
{
    void solve()
    {
        char a[100010];
        int sum =0, k, num[10];
        scanf("%d%s", &k, a);
        int lena = strlen(a);
        for(int i=0; i<lena; i++)
            sum += a[i] - '0';
        sort(a, a+lena);

        int p = 0;
        while(sum < k)
            sum += 9 - (a[p++] - '0');

        printf("%d\n", p);
    }
};
C. Star sky

The Cartesian coordinate system is set in the sky. There you can see n stars, the i-th has coordinates (xiyi), a maximum brightness c, equal for all stars, and an initial brightness si (0 ≤ si ≤ c).

Over time the stars twinkle. At moment 0 the i-th star has brightness si. Let at moment t some star has brightness x. Then at moment (t + 1) this star will have brightness x + 1, if x + 1 ≤ c, and 0, otherwise.

You want to look at the sky q times. In the i-th time you will look at the moment ti and you will see a rectangle with sides parallel to the coordinate axes, the lower left corner has coordinates (x1iy1i) and the upper right — (x2iy2i). For each view, you want to know the total brightness of the stars lying in the viewed rectangle.

A star lies in a rectangle if it lies on its border or lies strictly inside it.

Input

The first line contains three integers nqc (1 ≤ n, q ≤ 1051 ≤ c ≤ 10) — the number of the stars, the number of the views and the maximum brightness of the stars.

The next n lines contain the stars description. The i-th from these lines contains three integers xiyisi (1 ≤ xi, yi ≤ 1000 ≤ si ≤ c ≤ 10) — the coordinates of i-th star and its initial brightness.

The next q lines contain the views description. The i-th from these lines contains five integers tix1iy1ix2iy2i (0 ≤ ti ≤ 1091 ≤ x1i < x2i ≤ 1001 ≤ y1i < y2i ≤ 100) — the moment of the i-th view and the coordinates of the viewed rectangle.

Output

For each view print the total brightness of the viewed stars.

Examples
input
Copy
2 3 3
1 1 1
3 2 0
2 1 1 2 2
0 2 1 4 5
5 1 1 5 5
output
3
0
3

C题,给定二维棋盘上有n个点,点的亮度在0-c之间变化,给出起始亮度,做q次询问,每次给出对角线上两点确定一个矩形,给出一个时间,问此时矩形内所有点的亮度和。

这道题是卡在场上的一道题,原因是我推出了一个公式证明,所有t时间后的亮度和起始亮度和以及点数相关,与起始亮度无关。然后以为自己可以在O(1) 的时间内直接得出所询问的亮度和。然后就WA了全场,下来才发现自己推的结论是错误的。sad

然后正解是,做一个区间的前缀和(dp),然后用容斥原理可以计算出矩形内,各种亮度的点分别有多少个,然后对每种亮度分别求解。

namespace Solver
{
    void solve()
    {
        int n, q, c, x1, y1, x2, y2, s, t;
        memset(mp, 0, sizeof mp);
        memset(dp, 0, sizeof dp);
        scanf("%d%d%d", &n, &q, &c);
        c++;
        for(int i=0; i<n; i++)
        {
            scanf("%d%d%d", &x1, &y1, &s);
            mp[x1][y1][s]++;
        }
        for(int i=1; i<105; i++)
            for(int j=1; j<105; j++)
                for(int k=0; k<c; k++){
                    dp[i][j][k] = dp[i][j-1][k] + dp[i-1][j][k] - dp[i-1][j-1][k] + mp[i][j][k];
                    //if(dp[i][j][k]) printf("%d %d %d: %d\n", i, j, k, dp[i][j][k]);
                }
        for(int i=0; i<q; i++)
        {
            int ans, sum = 0;
            scanf("%d%d%d%d%d", &t, &x1, &y1, &x2, &y2);
            for(int k=0; k<c; k++)
            {
                ans = dp[x2][y2][k] - dp[x1-1][y2][k] - dp[x2][y1-1][k] + dp[x1-1][y1-1][k];
                //printf("%d: %d\n", k, ans);
                sum += ans*((k+t)%c);
            }

            printf("%d\n", sum);
        }
    }
};
D. Palindromic characteristics

Palindromic characteristics of string s with length |s| is a sequence of |s| integers, where k-th number is the total number of non-empty substrings of s which are k-palindromes.

A string is 1-palindrome if and only if it reads the same backward as forward.

A string is k-palindrome (k > 1) if and only if:

  1. Its left half equals to its right half.
  2. Its left and right halfs are non-empty (k - 1)-palindromes.

The left half of string t is its prefix of length ⌊|t| / 2⌋, and right half — the suffix of the same length. ⌊|t| / 2⌋ denotes the length of string tdivided by 2, rounded down.

Note that each substring is counted as many times as it appears in the string. For example, in the string "aaa" the substring "a" appears 3 times.

Input

The first line contains the string s (1 ≤ |s| ≤ 5000) consisting of lowercase English letters.

Output

Print |s| integers — palindromic characteristics of string s.

Examples
input
Copy
abba
output
6 1 0 0 

D题:引入了一个k阶回文串的概念,1阶回文串是指普通回文串,然后对于n>1,有n阶回文串的前半部分是n-1阶回文串。求给出一个串,输出1 ~ |s|的各阶回文串个数。

这道题首先可以证明,对于任意k阶回文串(k>1)他本身也是k-1阶回文串。然后我们就可以通过对所有相同对称轴下最长的回文串记录阶数,然后计算后缀和得到各阶回文串的数量。而我一开始的思路就是,枚举对称轴求解,然后不知道是手残还是思路错了一直WA,然后改变思路,枚举子串的起点,用manacher算法在O(n)复杂度内处理出范围内所有回文串,记录回文串结尾,然后顺序计算阶数。

#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;

const int maxn = 1e4+5;

char s[maxn];
int rl[maxn], ans[maxn], sum[maxn];
queue<int >q;

void manacher(string a, int len)
{
    int maxr = 0, pos = 0;

    s[0] = '#';
    for(int i=0; i<len; i++){
        s[i*2+1] = a[i];
        s[i*2+2] = '#';
    }
    /** 预处理字符串 避免讨论奇偶性**/

    for(int i=0; i<2*len+1; i++)
    {
        if(i <= maxr)
            rl[i] = min(rl[2*pos - i], maxr-i);
        else rl[i] = 1;

        while(i-rl[i]>=0 && i+rl[i]<2*len+1 && s[i-rl[i]] == s[i+rl[i]])
            rl[i]++;

        if(i+rl[i]-1 > maxr){
            maxr = i+rl[i]-1;
            pos = i;
        }
        if(rl[i] == i+1) q.push(i);
    }
}


int main()
{
    string a;
    memset(ans, 0, sizeof ans);
    memset(sum, 0, sizeof sum);

    cin>>a;
    int lena = a.length();
    for(int n=lena; n>0; n--)
    {
        int len = n;
        manacher(a, len);
        memset(sum, 0, sizeof sum);
        q.pop();
        while(!q.empty())
        {
            int now = q.front();
            int l = now - (now+1)/2;
            sum[now] = sum[l]+1;
            ans[sum[now]]++;
            q.pop();
        }
        a=a.substr(1, len);
    }


    for(int i=lena-1; i>0; i--)
        ans[i] += ans[i+1];

    for(int i=1; i<=lena; i++)
        printf("%d%c", ans[i], i==lena?'\n':' ');
}

因为枚举了起点,然后每次又跑了O(n)的manacher算法,所以复杂度是O(n^2)。

E. The penguin's game

Pay attention: this problem is interactive.

Penguin Xoriy came up with a new game recently. He has n icicles numbered from 1 to n. Each icicle has a temperature — an integer from 1 to 109Exactly two of these icicles are special: their temperature is y, while a temperature of all the others is x ≠ y. You have to find those special icicles. You can choose a non-empty subset of icicles and ask the penguin what is the bitwise exclusive OR (XOR) of the temperatures of the icicles in this subset. Note that you can't ask more than 19 questions.

You are to find the special icicles.

Input

The first line contains three integers nxy (2 ≤ n ≤ 10001 ≤ x, y ≤ 109x ≠ y) — the number of icicles, the temperature of non-special icicles and the temperature of the special icicles.

Output

To give your answer to the penguin you have to print character "!" (without quotes), then print two integers p1p2 (p1 < p2) — the indexes of the special icicles in ascending order. Note that "!" and p1 should be separated by a space; the indexes should be separated by a space too. After you gave the answer your program should terminate immediately.

Interaction

To ask a question print character "?" (without quotes), an integer c (1 ≤ c ≤ n), and c distinct integers p1p2, ..., pc (1 ≤ pi ≤ n) — the indexes of icicles that you want to know about. Note that "?" and c should be separated by a space; the indexes should be separated by a space too.

After you asked the question, read a single integer — the answer.

Note that you can't ask more than 19 questions. If you ask more than 19 questions or at least one incorrect question, your solution will get "Wrong answer".

If at some moment your program reads  - 1 as an answer, it should immediately exit (for example, by calling exit(0)). You will get "Wrong answer" in this case, it means that you asked more than 19 questions, or asked an invalid question. If you ignore this, you can get other verdicts since your program will continue to read from a closed stream.

Your solution will get "Idleness Limit Exceeded", if you don't print anything or forget to flush the output, including for the final answer .

To flush you can use (just after printing):

  • fflush(stdout) in C++;
  • System.out.flush() in Java;
  • stdout.flush() in Python;
  • flush(output) in Pascal;
  • For other languages see the documentation.

Hacking

For hacking use the following format:

n x y p1 p2

Here 1 ≤ p1 < p2 ≤ n are the indexes of the special icicles.

Contestant programs will not be able to see this input.

Example
input
Copy
4 2 1
2
1
1
output
? 3 1 2 3
? 1 1
? 1 3
! 1 3

E题:做的第一道互动形式的题目,大意是有n个数,其中有两个是y,其余的全部都是x。你能挑出一些集合,去询问他们的异或结果。最多询问19次。找出那两个的值是y,然后输出他们。

看到异或操作的第一反应就是一个数异或奇数次是本身,异或偶数次是0。然后就想到1024杯水试毒药的那个经典例子。其实第一步按位去选择集合异或,然后得出这两个special num的编号在各个位上的异或关系,在哪一位上是不一样的(至少有一位是不一样的),然后确定那一位就可以保证只取到一个special num。然后确定了一个就可以根据第一步的异或关系得出第二个数。

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

const int maxn = 1005;

bool pd[11], vis[11];

int q[maxn];

int main()
{
    int n, x, y, m=0, p;
    scanf("%d%d%d", &n, &x, &y);
    int temp = n;
    while(temp>0){
        m++;
        temp >>= 1;
    }

    for(int i=0; i<m; i++)
    {
        int tol = 0;
        for(int j=1; j<=n; j++){
            if( (j>>i)&1 ){
                q[tol++] = j;
            }
        }

        if(tol){
            printf("? %d ", tol);
            for(int j=0; j<tol; j++)
                printf("%d ", q[j]);
            printf("\n");
            fflush(stdout);
            scanf("%d", &temp);
            if(temp==x || temp==0) pd[i] = true;  //第i位相同
            else pd[i] = false;                   //第i位不同
        }
    }

    for(int i=0; i<m; i++)        // 第i位取1
        if(!pd[i]) {
            p = i; break;
        }

    vis[p] = true;
    for(int i=0; i<m; i++)
    {
        if(i==p) continue;


        int tol = 0;
        for(int j=1; j<=n; j++){
            if( (j>>i)&1 && (j>>p)&1 ){
                q[tol++] = j;
            }
        }

        if(tol){
            printf("? %d ", tol);
            for(int j=0; j<tol; j++)
                printf("%d ", q[j]);
            printf("\n");
            fflush(stdout);
            scanf("%d", &temp);
            if(temp==x || temp==0) vis[i] = false;  //第i位取0
            else vis[i] = true;                   //第i位取1
        }

        else vis[i] = false;
    }


    int ans1 = 0, ans2 = 0;

    for(int i=m-1; i>=0; i--)
    {
        ans1 <<= 1;
        if(vis[i]) ans1++;
    }

    for(int i=m-1; i>=0; i--)
    {
        ans2 <<= 1;
        if((vis[i] && pd[i]) || (!vis[i] && !pd[i])) ans2++;
    }

    if(ans1 > ans2) swap(ans1, ans2);

    printf("! %d %d\n", ans1, ans2);
}

思路不难但是手残了一个多小时,各种各样的bug和debug。还好在今天回寝室前做出来了Orz。而且这道题vj上少了一句话,要在输出后用fflush(stdout)。要不然会Idleness limit exceeded。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值