BestCoder 2nd Anniversary的前两题

Oracle

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 79    Accepted Submission(s): 41


Problem Description
There is once a king and queen, rulers of an unnamed city, who have three daughters of conspicuous beauty.

The youngest and most beautiful is Psyche, whose admirers, neglecting the proper worship of the love goddess Venus, instead pray and make offerings to her. Her father, the king, is desperate to know about her destiny, so he comes to the Delphi Temple to ask for an oracle.

The oracle is an integer n without leading zeroes.

To get the meaning, he needs to rearrange the digits and split the number into <b>two positive integers without leading zeroes</b>, and their sum should be as large as possible.

Help him to work out the maximum sum. It might be impossible to do that. If so, print `Uncertain`.
 
Input
The first line of the input contains an integer T (1T10), which denotes the number of test cases.

For each test case, the single line contains an integer n (1n<1010000000).
 
Output
For each test case, print a positive integer or a string `Uncertain`.
 
Sample Input
3 112 233 1
 
Sample Output
22 35 Uncertain
Hint
In the first example, it is optimal to split $ 112 $ into $ 21 $ and $ 1 $, and their sum is $ 21 + 1 = 22 $. In the second example, it is optimal to split $ 233 $ into $ 2 $ and $ 33 $, and their sum is $ 2 + 33 = 35 $. In the third example, it is impossible to split single digit $ 1 $ into two parts.
 
Source
 
题意:将一个大数分解成两个数字,要求两个数字是没有前导0的正整数,然后问相加的结果的最大值.
题解:先对输入的串从大到小排个序,如果输入的串长度为1或者 除了第一位全部都是 0,那么无解,其余的情况将第一个大于0的数取出来,然后剩下的数组成一个串相加即可。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
#define N 10000005
char str[N];
char result[N];
char b[100];
int cmp(char a,char b)
{
    return a>b;
}
void reverse( char *s )        /*将字符串逆置*/
{
    int length;
    int i = 0;
    char temp;
    length = strlen( s );
    while( i < length - i - 1 )
    {
        temp = s[i];
        s[i] = s[length - i - 1];
        s[length - i - 1] = temp;
        i++;
    }
}
void AddBigNum( char* s1, char* s2, char* result )
{
    int len1 = strlen( s1 );
    int len2 = strlen( s2 );
    int acc = 0, temp, i;        /*acc为进位标记*/
    if( s1 == NULL || s2 == NULL || result == NULL )
    {
        return;
    }
    reverse( s1 );
    reverse( s2 );
    for( i = 0; i < len1 && i < len2; i++ )
    {
        temp = s1[i] - '0' + s2[i] - '0' + acc;        /*计算每位的实际和*/
        result[i] = temp % 10 + '0';        /*通过求余数来确定每位的最终值*/
        if( temp >= 10 )        /*通过这个if..else..条件来判断是否有进位,并设置进位值*/
            acc = 1;
        else
            acc = 0;
    }
    if( i < len1 )        /*两个加数位数不同*/
    {
        for( ; i < len1; i++ )
        {
            temp = s1[i] - '0' + acc;        /*依旧要考虑进位,比如9999 + 1的情况*/
            result[i] = temp % 10 + '0';
            if( temp >= 10 )
                acc = 1;
            else
                acc = 0;
        }
    }
    if( i < len2 )
    {
        for( ; i < len2; i++ )
        {
            temp = s2[i] - '0' + acc;
            result[i] = temp % 10 + '0';
            if( temp >= 10 )
                acc = 1;
            else
                acc = 0;
        }
    }
    if( acc == 1 )        /*考虑如:123 + 911 = 1034的情况,如果不增加这个条件会得到结果为034,进位被舍弃*/
        result[i++] = '1';
    result[i] = '';
    reverse( result );
}
int main()
{
    int tcase;
    scanf("%d",&tcase);
    while(tcase--)
    {
        scanf("%s",str);
        int len = strlen(str);
        sort(str,str+len,cmp);
        if(len==1)
        {
            printf("Uncertain
");
        }
        else
        {
            bool flag = true;
            int ans = 0;
            for(int i=len-1; i>=0; i--)
            {
                if(str[i]!='0')
                {
                    ans = i;
                    break;
                }
            }
            if(ans==0)
            {
                printf("Uncertain
");
                continue;
            }
            b[0] = str[ans];
            int id = 0;
            for(int i=0; i<len; i++)
            {
                if(i==ans) continue;
                str[id++] = str[i];
            }
            str[id]='';
            AddBigNum(str,b,result);
            printf("%s
",result);
        }
    }
    return 0;
}

Arrange

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 74    Accepted Submission(s): 30


Problem Description
Accidentally, Cupid, god of desire has hurt himself with his own dart and fallen in love with Psyche.

This has drawn the fury of his mother, Venus. The goddess then throws before Psyche a great mass of mixed crops.

There are n heaps of crops in total, numbered from 1 to n.

Psyche needs to arrange them in a certain order, assume crops on the i-th position is Ai.

She is given some information about the final order of the crops:

1. the minimum value of A1,A2,...,Ai is Bi.

2. the maximum value of A1,A2,...,Ai is Ci.

She wants to know the number of valid permutations. As this number can be large, output it modulo 998244353.

Note that if there is no valid permutation, the answer is 0.
 
Input
The first line of input contains an integer T (1T15), which denotes the number of testcases.

For each test case, the first line of input contains single integer n (1n105).

The second line contains n integers, the i-th integer denotes Bi (1Bin).

The third line contains n integers, the i-th integer denotes Ci (1Cin).
 
Output
For each testcase, print the number of valid permutations modulo 998244353.
 
Sample Input
2 3 2 1 1 2 2 3 5 5 4 3 2 1 1 2 3 4 5
 
Sample Output
1 0
Hint
In the first example, there is only one valid permutation (2,1,3) . In the second example, it is obvious that there is no valid permutation.
 
Source
 
题意:在由 1 - n 中的数字组成的n个谷堆,假设前 i 个谷堆的最大值是C[i],最小值是B[i],现在知道这n堆谷堆前所有前缀的最大值和最小值,问这些谷堆总共有多少种组成方式??
题解:递推,排除掉5种不可能的情况,1.b[i]>b[i-1] 2,c[i]<c[i-1] 3,b[i]>c[i] 4.c[1]!=b[1] 5.b[i],c[i] < 1 || > n ,然后递推,如果当前产生的新的 b[i]或者 c[i] 那么dp[i] = dp[i-1] ,如果当前 b[i-1] = b[i] && c[i-1] = c[i] ,那么我们可以在 [b[i],c[i]]中任选一个数,但是由于谷堆是互不相同的,所以每次我们的选项都会变少,弄个计数器计算一下当前已经选了多少种,减掉之后答案即为 dp[i] = dp[i-1]*(c[i]-b[i]+1-num)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const long long mod = 998244353;
const int N = 100005;
int b[N],c[N];
long long dp[N];
int main()
{
    int tcase;
    scanf("%d",&tcase);
    while(tcase--)
    {
        int n;
        scanf("%d",&n);
        int MIN = 9999999;
        int MAX = -1;
        bool flag = true;
        for(int i=1;i<=n;i++){
            scanf("%d",&b[i]);
            if(b[i]<1||b[i]>n) flag = false;
            if(b[i]>MIN) flag = false;
            MIN = min(MIN,b[i]);
        }
        for(int i=1;i<=n;i++){
            scanf("%d",&c[i]);
            if(c[i]<MAX) flag = false;
            if(c[i]<1||c[i]>n) flag = false;
            MAX = max(MAX,c[i]);
            if(c[i]<b[i]) flag = false;
        }
        if(!flag||c[1]!=b[1]) printf("0
");
        else{
            memset(dp,0,sizeof(dp));
            dp[1] = 1;
            int num =1 ;
            for(int i=2;i<=n;i++){
                if(c[i]==c[i-1]&&b[i-1]==b[i]) {
                    dp[i] = dp[i-1]*(c[i]-b[i]-num+1)%mod;
                }
                else if(b[i]<b[i-1]&&c[i-1]==c[i]||b[i]==b[i-1]&&c[i-1]<c[i]){
                    dp[i] = dp[i-1];
                }
                num++;
            }
            printf("%I64d
",dp[n]);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/liyinggang/p/5679702.html