春季个人训练赛 9

**

A - Penney Game(4873)

**
Penney’s game is a simple game typically played by two players. One version of the game calls for each
player to choose a unique three-coin sequence such as HEADS TAILS HEADS (HTH). A fair coin is tossed
sequentially some number of times until one of the two sequences appears. The player who chose the first
sequence to appear wins the game.
For this problem, you will write a program that implements a variation on the Penney Game. You will read a
sequence of 40 coin tosses and determine how many times each three-coin sequence appears. Obviously there
are eight such three-coin sequences: TTT, TTH, THT, THH, HTT, HTH, HHT and HHH. Sequences may
overlap. For example, if all 40 coin tosses are heads, then the sequence HHH appears 38 times.
Input
The first line of input contains a single integer P, (1 P 1000), which is the number of data sets that follow.
Each data set consists of 2 lines. The first line contains the data set number N. The second line contains the
sequence of 40 coin tosses. Each toss is represented as an upper case H or an upper case T, for heads or tails,
respectively. There will be no spaces on any input line.
Output
For each data set there is one line of output. It contains the data set number followed by a single space,
followed by the number of occurrences of each three-coin sequence, in the order shown above, with a space
between each one. There should be a total of 9 space separated decimal integers on each output line.

Sample Input
4
1
HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
2
TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
3
HHTTTHHTTTHTHHTHHTTHTTTHHHTHTTHTTHTTTHTH
4
HTHTHHHTHHHTHTHHHHTTTHTTTTTHHTTTTHTHHHHT

Sample Output
1 0 0 0 0 0 0 0 38
2 38 0 0 0 0 0 0 0
3 4 7 6 4 7 4 5 1
4 6 3 4 5 3 6 5 6

题意:给一串字符串,求 TTT, TTH, THT, THH, HTT, HTH, HHT and HHH 的个数
思路:
用的是 c++ 中的 substr 函数,从该位置截取3个数字,比对相应的字符

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
typedef long long LL;
using namespace std;
#define memset(a,n) memset(a,n,sizeof(a))
#define INF 0x3f3f3f3f


int main()
{
    int t,k;
    string s,c;

    string ss[8]={"TTT","TTH","THT","THH","HTT","HTH","HHT","HHH"};

    int a[10];
    cin>>t;

    while(t--)
    {
        memset(a,0);

        cin>>k>>s;

        for(int i=0;i<s.size()-2;i++){
            c=s.substr(i,3);
            
            for(int i=0;i<8;i++)
                if(ss[i]==c)
                    a[i]++;
        }

        cout<<k;
        for(int i=0;i<8;i++){
            cout<<' '<<a[i];
        }
        cout<<endl;
    }

}

**

2、B - Nim-B Sum(4874)

**

The game of NIM is played with any number of piles of objects with any number of objects in each pile. At
each turn, a player takes one or more (up to all) objects from one pile. In the normal form of the game, the
player who takes the last object is the winner. There is a well-known strategy for this game based on the
nim-2 sum.
The Nim-B sum (nim sum base B) of two non-negative integers X and Y (written NimSum(B, X, Y)) is
computed as follows:

  1. Write each of X and Y in base B.
    Each digit in base B of the Nim-B sum is the sum modulo B of the corresponding digits in the base B
    representation of X and Y.

For example:
NimSum(2, 123, 456) = 1111011¤111001000 = 110110011 = 435
NimSum(3, 123, 456) = 11120¤121220 = 102010 = 300
NimSum(4, 123, 456) = 1323¤13020 = 10303 = 307

The strategy for normal form Nim is to compute the Nim-2 sum T of the sizes of all piles. If at any time, you
end your turn with T = 0, you are guaranteed a WIN. Any opponent move must leave T not 0 and there is
always a move to get T back to 0. This is done by computing NimSum(2, T, PS) for each pile; if this is less
than the pile size (PS), compute the difference between the PS and the Nim-2 sum and remove it from that
pile as your next move.
Write a program to compute NimSum(B, X, Y).

Input
The first line of input contains a single integer P, (1 P 1000), which is the number of data sets that follow.
Each data set is a single line that contains the data set number, followed by a space, followed by three space
separated decimal integers, B, X and Y. 2 B 2000000, 0 X 2000000, 0 Y 2000000.

Output
For each data set there is one line of output. It contains the data set number followed by a single space,
followed by N, the decimal representation of the Nim sum in base B of X and Y.

Sample Input
4
1 2 123 456
2 3 123 456
3 4 123 456
4 5 123 456

Sample Output
1 435
2 300
3 307
4 429

题意:
NimSum(B, X, Y) ,B是几进制,X、Y是两个操作数
将X、Y转化成B进制数,每一位相加对 B 求余,得到B进制数,然后再转化成十进制

注意,X、Y的位数可能不样
例如:B=2
1 1 0 1 1
0 1 1 1
结果:
1 1 1 0 0 将两个数右对齐,左边多出的就原样复制下来

思路:
先转化成B进制数,然后根据位数的不同进行不同的操作,相加时用同余定理

求B进制数的时候,在数组里是倒着存的,所以想加的时候,左对齐,多余的是右边剩余的数字
然后转化成十进制的时候,从左到右进行

CODE:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
typedef long long LL;
using namespace std;
#define memset(a,n) memset(a,n,sizeof(a))
#define INF 0x3f3f3f3f
const LL MAX = 1e7+10;
LL s[MAX],ss[MAX];
LL ans[MAX];

int main()
{
    int t,k;
    LL b,x,y;

    scanf("%d",&t);

    while(t--)
    {
        memset(s,0);
        memset(ss,0);
        memset(ans,0);

        scanf("%d %lld %lld %lld",&k,&b,&x,&y);

        LL cnt=0;

      // 将x、y转化成 B进制数
        while(x)
        {
            s[cnt++]=x%b;
            x/=b;
        }

        LL cnt1=0;

        while(y)
        {
            ss[cnt1++]=y%b;
            y/=b;
        }

        LL flag=0;
        LL xx,yy;

        if(cnt==cnt1)    // 位数相同直接相加
        {
            for(LL i=0;i<cnt;i++)
            {
                xx=s[i];
                yy=ss[i];
                ans[flag++]=((xx%b)+(yy%b))%b;
                if(ans[flag-1]<0)
                    ans[flag-1]+=b;
            }
        }

      // 位数多的直接把多余的复制下来
        else if(cnt>cnt1)   // 这里因为 else if 哇了一次!!(我写成了if)
        {
            for(LL i=0;i<cnt1;i++){
                ans[flag++]=((s[i]%b)+(ss[i]%b))%b;
                if(ans[flag-1]<0)
                    ans[flag-1]+=b;
            }

            for(LL i=cnt1;i<cnt;i++){
                ans[flag++]=s[i]%b;
                if(ans[flag-1]<0)
                    ans[flag-1]+=b;
            }
        }

        else{

            for(LL i=0;i<cnt;i++){
                ans[flag++]=((s[i]%b)+(ss[i]%b))%b;
                if(ans[flag-1]<0)
                    ans[flag-1]+=b;
            }

            for(LL i=cnt;i<cnt1;i++){
                ans[flag++]=ss[i]%b;
                if(ans[flag-1]<0)
                    ans[flag-1]+=b;
            }
        }


        LL sum=0;
        LL tt=1;
        
         // 转化成十进制
        for(LL i=0;i<flag;i++){
            if(ans[i]!=0){
                sum+=ans[i]*tt;
            }
            tt*=b;
        }

       printf("%d %lld\n",k,sum);
    }
}

**

3、 Non-Decreasing Digits(4877)

**
A number is said to be made up of non-decreasing digits if all the digits to the left of any digit is less
than or equal to that digit. For example, the four-digit number 1234 is composed of digits that are nondecreasing.
Some other four-digit numbers that are composed of non-decreasing digits are 0011, 1111,
1112, 1122, 2223. As it turns out, there are exactly 715 four-digit numbers composed of non-decreasing
digits.
Notice that leading zeroes are required: 0000, 0001, 0002 are all valid four-digit numbers with
non-decreasing digits.
For this problem, you will write a program that determines how many such numbers there are with
a specified number of digits.
Input
The first line of input contains a single integer P (1 ≤ P ≤ 1000), which is the number of data sets that
follow. Each data set is a single line that contains the data set number, followed by a space, followed
by a decimal integer giving the number of digits N (1 ≤ N ≤ 64).
Output
For each data set there is one line of output. It contains the data set number followed by a single space,
followed by the number of N digit values that are composed entirely of non-decreasing digits.
Sample Input
3
1 2
2 3
3 4
Sample Output
1 55
2 220
3 715

题意:
用 0 - 9 组成 n 位不递减的序列(可以相等或者递增 , 000、 001 、 111 、122 等都是合法的)
求n位数满足题意的有几种可能?

思路:
dp题
当 n 等于2的时候,以 0 - 9开头的数目依次为 10 、 9 、 … … 1
当 n 等于3的时候:
以0开头,在 n 等于 2的时候的结果都可以,0 都可以放在上一次数的前边,所以以0开头的数目为上一次的值
以1开头,只能放在上一次以 1 、 2 、3 … 9 的 数字后边,所以是上次 1 - 9 的数目之和
以2开头,只能放在上一次以 2 、 3 、4 …9 的 数字后边,所以是上一次 2 - 9 的数目之和

所以:

for(int j=0;j<=9;j++){
   if(j==0)    //  以 0 开头的结果
          dp[j]=ans[i-1];
   else{
           for(int k=j;k<=9;k++) 
                sum+=dp[k];   // j - 9 的结果之和等于 j 的结果
            dp[j]=sum;
             sum=0;
          }
}
for(int j=0;j<=9;j++)
    ans[i]+=dp[j];   // 记录一下这一次的总数目

CODE:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
typedef long long LL;
using namespace std;
#define memset(a,n) memset(a,n,sizeof(a))
#define INF 0x3f3f3f3f
const LL MAX = 1e7+10;

LL dp[12];
LL ans[100];

int main()
{
    int t,k;
    int n;
    cin>>t;

    for(int i=0;i<=9;i++)
        dp[i]=10-i;

    LL sum=0;
    memset(ans,0);

    ans[1]=10;
    ans[2]=55;

    for(int i=3;i<=64;i++)
    {
        for(int j=0;j<=9;j++){
            if(j==0)
                dp[j]=ans[i-1];
            else{
                for(int k=j;k<=9;k++)
                    sum+=dp[k];
                dp[j]=sum;
                sum=0;
            }
        }

         for(int j=0;j<=9;j++)
            ans[i]+=dp[j];
    }


    while(t--)
    {
        cin>>k>>n;
        cout<<k<<' '<<ans[n]<<endl;
    }
}

猜你喜欢

转载自blog.csdn.net/JKdd123456/article/details/88916879