Codeforces Round #289 (Div. 2, ACM ICPC Rules)

54 篇文章 0 订阅
53 篇文章 0 订阅

比赛链接:http://codeforces.com/contest/509


A. Maximum in Table
time limit per test 2 seconds
memory limit per test 256 megabytes


An n × n table a is defined as follows:

The first row and the first column contain ones, that is: ai, 1 = a1, i = 1 for all i = 1, 2, ..., n.
Each of the remaining numbers in the table is equal to the sum of the number above it and the number to the left of it. In other words, the remaining elements are defined by the formula ai, j = ai - 1, j + ai, j - 1.
These conditions define all the values in the table.

You are given a number n. You need to determine the maximum value in the n × n table defined by the rules above.

Input
The only line of input contains a positive integer n (1 ≤ n ≤ 10) — the number of rows and columns of the table.

Output
Print a single line containing a positive integer m — the maximum value in the table.

Sample test(s)
input
1
output
1
input
5
output
70
Note
In the second test the rows of the table look as follows:

{1, 1, 1, 1, 1}, 
{1, 2, 3, 4, 5}, 
{1, 3, 6, 10, 15}, 
{1, 4, 10, 20, 35}, 
{1, 5, 15, 35, 70}.


题目分析:根据递推公式推即可


#include <cstdio>
int dp[11][11];
int main()
{
    int n;
    scanf("%d", &n);
    for(int i = 1; i < 11; i++)
        dp[1][i] = 1;
    for(int i = 2; i < 11; i++)
        for(int j = 1; j < 11; j++)
            dp[i][j] = dp[i][j - 1] + dp[i - 1][j];
    printf("%d\n", dp[n][n]);
}   




B. Painting Pebbles
time limit per test 1 second
memory limit per test 256 megabytes


There are n piles of pebbles on the table, the i-th pile contains ai pebbles. Your task is to paint each pebble using one of the k given colors so that for each color c and any two piles i and j the difference between the number of pebbles of color c in pile i and number of pebbles of color c in pile j is at most one.

In other words, let's say that bi, c is the number of pebbles of color c in the i-th pile. Then for any 1 ≤ c ≤ k, 1 ≤ i, j ≤ n the following condition must be satisfied |bi, c - bj, c| ≤ 1. It isn't necessary to use all k colors: if color c hasn't been used in pile i, then bi, c is considered to be zero.

Input
The first line of the input contains positive integers n and k (1 ≤ n, k ≤ 100), separated by a space — the number of piles and the number of colors respectively.

The second line contains n positive integers a1, a2, ..., an (1 ≤ ai ≤ 100) denoting number of pebbles in each of the piles.

Output
If there is no way to paint the pebbles satisfying the given condition, output "NO" (without quotes) .

Otherwise in the first line output "YES" (without quotes). Then n lines should follow, the i-th of them should contain ai space-separated integers. j-th (1 ≤ j ≤ ai) of these integers should be equal to the color of the j-th pebble in the i-th pile. If there are several possible answers, you may output any of them.

Sample test(s)
input
4 4
1 2 3 4
output
YES
1
1 4
1 2 4
1 2 3 4
input
5 2
3 2 4 1 3
output
NO
input
5 4
3 2 4 3 5
output
YES
1 2 3
1 3
1 2 3 4
1 3 4
1 1 2 3 4


题目大意:有n堆物品,k种颜色,每堆有a[i]个物品,问如何着色可以使任意两堆任意一种颜色的数量差不大于1,不存在这种着色方案输出NO

题目分析:根据抽屉原理我们可以发现当max(a[i]) - min(a[i]) > k的时候是不存在的,否则按顺序循环输出即可


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int vis[105], a[105];

int main()
{
    int n, k, ma = -1, mi = 200;
    memset(vis, 0, sizeof(vis));
    scanf("%d %d", &n, &k);
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        ma = max(ma, a[i]);
        mi = min(mi, a[i]);
    }
    if(ma - mi > k)
    {
        printf("NO\n");
        return 0;
    }
    printf("YES\n");
    for(int i = 1; i <= n; i++)
    {
        int num = 1;
        for(int j = 1; j < a[i]; j++)
        {
            if(num > k)
                num = num % k;
            if(num % k == 0)
                num = num % k + k;
            printf("%d ", num++);
        }
        printf("%d\n", num % k == 0 ? num % k + k : num % k);
    }
}




C. Sums of Digits
time limit per test
2 seconds
memory limit per test
256 megabytes

Vasya had a strictly increasing sequence of positive integersa1, ..., an. Vasya used it to build a new sequenceb1, ..., bn, where bi is the sum of digits ofai's decimal representation. Then sequenceai got lost and all that remained is sequencebi.

Vasya wonders what the numbers ai could be like. Of all the possible options he likes the one sequence with the minimum possible last numberan. Help Vasya restore the initial sequence.

It is guaranteed that such a sequence always exists.

Input

The first line contains a single integer number n (1 ≤ n ≤ 300).

Next n lines contain integer numbersb1, ..., bn  — the required sums of digits. Allbi belong to the range1 ≤ bi ≤ 300.

Output

Print n integer numbers, one per line — the correct option for numbersai, in order of following in sequence. The sequence should be strictly increasing. The sum of digits of thei-th number should be equal to bi.

If there are multiple sequences with least possible numberan, print any of them. Print the numbers without leading zeroes.

Sample test(s)
Input
3
1
2
3
Output
1
2
3
Input
3
3
2
1
Output
3
11
100

题目大意:给你一组数字每位的和组成的序列,现在要找到原数字组成的序列,该序列是一个严格递增序列, 要求最后一个数字是在所有满足条件的序列中最小的


题目分析:我们根据上一个数字来推出下一个数字,方法是先计算当前位和与前一个位和的差

1.如果差值大于0,直接从上一个数字的最低位开始累加差值,满10进1

2.如果差值小于0,则先从上一个数字的低位依次往后累加差值,直到差值大于0,这里的操作相当于减去上一位数字多出来的部分再进行1操作,举个例子

5
6
10
18
16
7

答案是

6
19
99
169
205

首先 第一个数字肯定不变,接着10,10-6=4>0,因此我们直接从6开始枚举6+3=9因为4-3=1差一位则进位,得到19

18-10=8>0从19的最低位枚举,因为最低位为9,因此从十位枚举,十位是1,加上差值8即十位变成9,得到99

18-16=-2<0 这时要先让差值大于0,在99的最低位9减去2,得到7,将最低位归0,因为第二位也是9,还要进位,进位的时候差值要累加9得到16,十位0,最后我们其实把问题转变为,从100开始找十位和个位和为15的最小数,直接从低位枚举就行了,因为15>9,所以个位就是9,十位是15-9=6,最后得169,一开始得到7时因为97<99,因此我们必须要进位,还有将最低位归0得操作是因为我们要找的是大于前一个数的最小数,因此要从0开始枚举

7-16=-9<0 这时要先让差值大于0,在169最低位9减去9,得到0,将最低位归0,这时候d=0,则加上十位6,十位归0,百位加1,差值减1,转变为从200开始找十位和个位和为5的最小数,枚举得到205.



#include <cstdio>
#include <cstring>
int digit[1000], len = 0;

void next(int d)
{
    for(int i = 1; d > 0; i++) //从低位枚举
    {
        while(d > 0 && digit[i] < 9)
        {
            d--;
            digit[i]++;
        }
        len = i > len ? i : len; //进位的时候要注意更改位数
    }
}

int main()
{
    int n, b[400];
    scanf("%d", &n);
    b[0] = 0;
    for(int i = 1; i <= n; i++)
        scanf("%d", &b[i]);
    for(int i = 1; i <= n; i++)
    {
        int d = b[i] - b[i - 1];
        if(d > 0)
            next(d);
        else 
        {
            for(int i = 1; ; i++)
            {
                len = i > len ? i : len;
                if(d > 0 && digit[i] < 9)
                {
                    d--;
                    digit[i]++;
                    next(d);
                    break;
                }
                d += digit[i];
                digit[i] = 0;
            }
        }
        for(int i = len; i >= 1; i--)
            printf("%d", digit[i]);
        printf("\n");
    }
}




E. Pretty Song
time limit per test 1 second
memory limit per test 256 megabytes


When Sasha was studying in the seventh grade, he started listening to music a lot. In order to evaluate which songs he likes more, he introduced the notion of the song's prettiness. The title of the song is a word consisting of uppercase Latin letters. The prettiness of the song is the prettiness of its title.

Let's define the simple prettiness of a word as the ratio of the number of vowels in the word to the number of all letters in the word.

Let's define the prettiness of a word as the sum of simple prettiness of all the substrings of the word.

More formally, let's define the function vowel(c) which is equal to 1, if c is a vowel, and to 0 otherwise. Let si be the i-th character of string s, and si..j be the substring of word s, staring at the i-th character and ending at the j-th character (sisi + 1... sj, i ≤ j).

Then the simple prettiness of s is defined by the formula:


The prettiness of s equals


Find the prettiness of the given song title.


We assume that the vowels are I, E, A, O, U, Y.

Input
The input contains a single string s (1 ≤ |s| ≤ 5·105) — the title of the song.

Output
Print the prettiness of the song with the absolute or relative error of at most 10 - 6.

Sample test(s)
input
IEAIAIO
output
28.0000000
input
BYOB
output
5.8333333
input
YISVOWEL
output
17.0500000
Note
In the first sample all letters are vowels. The simple prettiness of each substring is 1. The word of length 7 has 28 substrings. So, the prettiness of the song equals to 28.


题目大意:输入一个字符串,若字符为I, E, A, O, U, Y中的一个,则这个字符的值为1,否则为0,该字符串的所有子串都有一个值,为该子串的所有字符的值的和除以其串长,最终的值为所有子串的值的和

例如样例2,其子串和值分别为 B 0, Y 1, O 1, B 0, BY 1/2, YO 1, OB 1/2, BYO 2/3, YOB 2/3, BYOB 1/2

最后结果就是0 + 1 + 1 + 0 + 1/2 + 1 + 1/2 + 2/3 + 2/3 + 1/2 = 11/6 = 5.8333333....


题目分析:因为字符串给的范伟太大,暴力不可做,我们可以发现对于每一个字符,它在相应长度的子串中出现的次数是固定的

例如ABCDEFG对于长度为1的都出现了7次,对于长度为2的AG出现一次,BCDEF出现两次,对于长度为3的AG出现1次,BF出现2次,CDE出现3次,以此类推

有了这个结论,我们可以先把前缀子串的前缀值求出来,然后依次向中间靠拢累加各个长度子串值的和,说得有点变扭,例如样例2

BYOB 我们可以得到sum[0] = 0 sum[1] = 0 sum[2] = 1 sum[3] = 2 sum[4] = 2,用sum[4] - sum[0]表示长度为1的子串的所有字符值的和即B = 0 Y = 1, O = 1等于2再用2除以1就是子串长为1的值,然后sum[3] - sum[1]注意这里要累加上前面的sum[4] - sum[0]因为这里的串长为2,sum[3] - sum[1]表示的是YO还有BY和YO要加上去结果是4,也可以理解为Y和O在串长为2的情况下都出现了两次,再用4除以2就是子串长为2的值,往后变成负值相当于减,因为拿ABCDEFG说,出现长度为1的和长度为7的和值是相同的,这很显然,出现长度为2和长度为6的和值也是相同的(AB)(BC)(CD)(DE)(EF)(FG)和(ABCDEF)(BCDEFG)我们可以发现A和G只计算了一次,BCDEF都算了两次,以此类推,所以长度过半以后再不断减去累加值即可


#include <cstdio> 
#include <cstring>
int const MAX = 500005;  
char s[MAX];  
int sum[MAX];  
  
int main()  
{  
    double ans = 0, tmp = 0;
    scanf("%s", s + 1);
    int len = strlen(s + 1);  
    memset(sum, 0, sizeof(sum));  
    for(int i = 1; i <= len; i++)  
    {  
        if(s[i] == 'I' || s[i] == 'E' || s[i] == 'A' || s[i] == 'O' || s[i] == 'U' || s[i] == 'Y')  
            sum[i] = sum[i - 1] + 1;
        else
            sum[i] = sum[i - 1];  
    }  
     for(int i = 0; i <= len; i++)
          printf("sum[%d] = %d\n", i, sum[i]);
    int l = 0, r = len;  
    for(int i = 1; i <= len; i++)  
    {  
        tmp += (sum[r--] - sum[l++]);  
        printf("tmp = %lf\n", tmp);
        ans += tmp / i;  
    }  
    printf("%.6lf\n", ans);    
}



F. Progress Monitoring
time limit per test 1 second
memory limit per test 256 megabytes


Programming teacher Dmitry Olegovich is going to propose the following task for one of his tests for students:

You are given a tree T with n vertices, specified by its adjacency matrix a[1... n, 1... n]. What is the output of the following pseudocode?


used[1 ... n] = {0, ..., 0};

procedure dfs(v):
    print v;
    used[v] = 1;
    for i = 1, 2, ..., n:
        if (a[v][i] == 1 and used[i] == 0):
            dfs(i);

dfs(1);
In order to simplify the test results checking procedure, Dmitry Olegovich decided to create a tree T such that the result is his favorite sequence b. On the other hand, Dmitry Olegovich doesn't want to provide students with same trees as input, otherwise they might cheat. That's why Dmitry Olegovich is trying to find out the number of different trees T such that the result of running the above pseudocode with T as input is exactly the sequence b. Can you help him?

Two trees with n vertices are called different if their adjacency matrices a1 and a2 are different, i. e. there exists a pair (i, j), such that 1 ≤ i, j ≤ n and a1[i][j] ≠ a2[i][j].

Input
The first line contains the positive integer n (1 ≤ n ≤ 500) — the length of sequence b.

The second line contains n positive integers b1, b2, ..., bn (1 ≤ bi ≤ n). It is guaranteed that b is a permutation, or in other words, each of the numbers 1, 2, ..., n appears exactly once in the sequence b. Also it is guaranteed that b1 = 1.

Output
Output the number of trees satisfying the conditions above modulo 109 + 7.

Sample test(s)
input
3
1 2 3
output
2
input
3
1 3 2
output
1


题目大意:给一个序列b[i],问通过题目所给伪代码深搜出来遍历路径和序列b[i]相同的树有多少种,结果对1e9 + 7取余


题目分析:又是和树有关,和287的C类似,这题还简单一点,由于题目说了b1肯定等于1,也就是根确定,因为要按照1,2...n的顺序深搜,我们可以取一段区间,开始就是1到n-1,(注意不是从0开始,因为根确定了)进行深搜,我们按照增序来找

1.当满足b[l] < b[i + 1]时,子树可以继续分解,分解成两部分,显然一部分把l当作根,另一部分把i当作根,根据乘法原理

ans = (ans + DFS(l + 1, i) * DFS(i + 1, r))

2.当i == r时,最右端的端点可以单独成一棵子树,例如4   1 2 4 3这个3可以单独当作右子树,而4   1 4 3 2我们不能把3 2部分单独放在右子树,因为这样必有和4在同一层的,4肯定后访问了,这里i == r这个条件不加样例都过不了,在这里想了半天。。弱爆了,如果l>r则说明找到了一组子树情况,为什么是大于号,因为我们是从当前根的后一个结点往下搜的。

最后注意一点,用dp记忆化搜索,不然T成狗


#include <cstdio>
#include <cstring>
#define ll long long
int const MAX = 505;
int const MOD = 1e9 + 7;
ll dp[MAX][MAX];
int b[MAX];

ll DFS(int l, int r) 
{
    ll ans = dp[l][r];
    if(ans >= 0) 
        return ans;
    if(l > r) 
        return 1;
    ans = 0;
    for(int i = l; i <= r; i++)
        if(i == r || b[l] < b[i + 1])
            ans = (ans + DFS(l + 1, i) * DFS(i + 1, r)) % MOD;  
    dp[l][r] = ans % MOD;
    return ans % MOD;
}

int main() 
{
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
        scanf("%d", &b[i]);
    memset(dp, -1, sizeof(dp));
    int res = DFS(1, n - 1);
    printf("%d\n", res);
}


前面的题一会儿补

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值