组队赛——NO.5

1、Which Base is it Anyway?

Programming languages such as C++ and Java can prefix characters to denote the base of constant
integer values. For example, hexadecimal (base 16) constants are preceded by the string “0x”. Octal
(base 8) values are preceded by the character “0” (zero). Decimal (base 10) values do not have a prefix.
For example, all the following represent the same integer constant, albeit in different bases.
0x1234
011064
4660
The prefix makes it clear to the compiler what base the value is in. Without the “0x” prefix, for
example, it would be impossible for the compiler to determine if 1234 was hexadecimal. It could be
octal or decimal.
For this problem, you will write a program that interprets a string of decimal digits as if it were an
octal value, a decimal value or a hexadecimal value.
Input
The first line of input contains a single decimal integer P , (1 ≤ P ≤ 10000), which is the number of
data sets that follow. Each data set should be processed identically and independently.
Each data set consists of a single line of input. It contains the data set number, K, followed by a
single space, followed by a string of at most 7 decimal digits.
Output
For each data set there is one line of output. The single output line consists of the data set number,
K, followed by a space followed by 3 space separated decimal integers which are the value of the input
as if it were interpreted to as octal, decimal and hexadecimal respectively. If the input value cannot be
interpreted as an octal value, use the value ‘0’.

输入:

4
1 1234
2 9
3 1777
4 129

输出:

1 668 1234 4660
2 0 9 9
3 1023 1777 6007
4 0 129 297

题意:

给定数字n,当它是八进制、十进制、十六进制时,输出相应的十进制

需要注意:当n为八进制的时候,范围是 0 - 7,如果n中出现数字 8、9都是不符合题意的,输出 0

 

CODE:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;

typedef long long LL;
#define memset(a,n) memset(a,n,sizeof(n))

int pow(int a,int b)
{
    int ans=1;
    while(b)
    {
        if(b&1)
            ans*=a;
        a*=a;
        b>>=1;
    }
    return ans;
}

int Tran(int m,int x)
{
    int ans=0,cnt=0;
    int flag;
    while(m)
    {
        flag=m%10;
        if(x==8)
        {
            if(flag>=8)
                return 0;
        }
        m/=10;
        ans+=flag*pow(x,cnt++);
    }
    return ans;

}

int main()
{
    int t,n,num,m;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d %d",&num,&m);
        printf("%d %d %d %d\n",num,Tran(m,8),m,Tran(m,16));
    }
}

 

2、FBI Universal Control Numbers

The FBI has recently changed its Universal Control Numbers (UCN ) for identifying individuals who
are in the FBI’s fingerprint database to an eight digit base 27 value with a ninth check digit. The digits
used are:
                              0123456789ACDEFHJKLMNPRTVWX
Some letters are not used because of possible confusion with other digits:
                               B->8, G->C, I->1, O->0, Q->0, S->5, U->V, Y->V, Z->2
The check digit is computed as:
 (2 ∗ D 1 + 4 ∗ D 2 + 5 ∗ D 3 + 7 ∗ D 4 + 8 ∗ D 5 + 10 ∗ D 6 + 11 ∗ D 7 + 13 ∗ D 8 ) mod 27
Where D n is the n-th digit from the left.
This choice of check digit detects any single digit error and any error transposing an adjacent pair
of the original eight digits.
For this problem, you will write a program to parse a UCN input by a user. Your program should
accept decimal digits and any capital letter as digits. If any of the confusing letters appear in the input,
you should replace them with the corresponding valid digit as listed above. Your program should
compute the correct check digit and compare it to the entered check digit. The input is rejected if they
do not match otherwise the decimal (base 10) value corresponding to the first eight digits is returned.


Input
The first line of input contains a single decimal integer P , (1 ≤ P ≤ 10000), which is the number of
data sets that follow. Each data set should be processed identically and independently.
Each data set consists of a single line of input. It contains the data set number, K, followed by a
single space, followed by 9 decimal digits or capital (alphabetic) characters.


Output
For each data set there is one line of output. The single output line consists of the data set number, K,
followed by a single space followed by the string ‘Invalid!’ (without the quotes) or the decimal value
corresponding to the first eight digits.


Sample Input

3
1 12345678A
2 12435678A
3 12355678A

Sample Output

1 11280469652
2  Invalid
3  Invalid 
 

题意:

给定包含九个字符的字符串,由 0123456789ACDEFHJKLMNPRTVWX 这27个字符组成的(也就是他的二十七进制)、

由于   B->8, G->C, I->1, O->0, Q->0, S->5, U->V, Y->V, Z->2 这几个字母容易混淆,所以相应的转化成对应的字符

比如出现 B 时,转化成 8,出现G时,转化成C

 

对输入的字符进行如下如下操作:

(2 ∗ D 1 + 4 ∗ D 2 + 5 ∗ D 3 + 7 ∗ D 4 + 8 ∗ D 5 + 10 ∗ D 6 + 11 ∗ D 7 + 13 ∗ D 8 ) mod 27

如果结果和 字符串的最后一个字符的值相等的话,那么输出 这个字符串对应的十进制数,否则输出 Invalid 

 

思路:

首先用 map 存下来字符对应的值是多少,特别注意混淆字母的值

其次注意输入的这九个字符可能出现数字字母还有混淆字母

首先用公式求出值是否和 S[9] 相等,然后再去转化为二十七进制

 

CODE:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;

typedef long long LL;
#define memset(a,n) memset(a,n,sizeof(n))

map<char,LL>M;
LL vis[10000+10];
char s[20]={"BGIOQSUYZ"};
char t[20]={"8C1005VV2"};
char S[20];


void Tran()   //  转化
{
    int flag=10;
    memset(vis,0);

    for(int i=0;i<9;i++) // 标记混淆字母的出现
    {
        vis[s[i]]=1;
    }

    for(char i='0';i<='9';i++) // 转化数字
        M[i]=i-'0';

    for(char i='A';i<='Z';i++)  // 转化字母
    {
        if(vis[i]==0)
            M[i]=flag++;
    }

    for(int i=0;i<9;i++)  // 转化混淆字母
    {
        M[s[i]]=M[t[i]];
    }
}


LL Judge()
{
    LL flag;
    LL ans=0,cnt=0;
    for(int i=7;i>=0;i--)
    {
        ans+=M[S[i]]*pow(27,cnt++);  // 转化为二十七进制,注意用字符串每一位的转化,而不是这一位的字符
    }
    return ans;
}

LL Judge1()
{
    LL flag,flag1;
    LL ans=0,cnt=0;
    LL tep=13,temp=11;   // 注意公式 每隔一项和前两项成等差数列

    for(int i=7;i>=0;i--)
    {
        if(i%2!=0)
        {
            flag=(M[S[i]]%27)*(tep%27)%27;
         
            tep-=3;
            ans+=flag;
        }
        else
        {
            flag=(M[S[i]]%27)*(temp%27)%27;
      
            temp-=3;
            ans+=flag;
        }
    }
    return ans%27;
}
int main()
{
    char c;
    LL m,ans,ans1,num;
    int t;
    scanf("%d",&t);

    m=0;
    while(t--)
    {
        Tran();
        m=0;
        memset(S,0);
        scanf("%lld ",&num);
        gets(S);
        c=S[8];

        ans=Judge1();
        if(ans==M[c])
            printf("%lld %lld\n",num,Judge()); 
        else
        {
            printf("%lld ",num);
            printf("Invalid\n");
        }



    }
}

 

3、

DA-Sort

You recently learned a new way to sort an array of numbers in your algorithms course. The algorithm
sorts an array of numbers by repeatedly performing the Delete-and-Append operation. The Delete-and-
Append operation consists of three steps:
1) Choose an element from the array.
2) Delete the chosen element from the array.
3) Append the chosen element to the end of the array.
Being a curious student, you wonder what is the minimum number of Delete-and-Append operations
required to sort a given array.


Input
The first line of input contains a single decimal integer P , (1 ≤ P ≤ 100), which is the number of data
sets that follow. Each data set should be processed identically and independently.
Each data set consists of two or more lines of input. The first line contains the data set number, K,
followed by a single space, followed by an integer N , (1 ≤ N ≤ 1000), which is the length of the array
to sort. The remaining lines in the dataset contains N positive integers that comprise the array to be
sorted, 10 values per line, except for the last line which may have less than 10 values. All the array
elements are no larger than 10 9 . The same value may appear more than once in the array to be sorted.


Output
For each data set there is one line of output. The single output line consists of the data set number, K,
followed by a single space followed by an integer which is the minimum number of Delete-and-Append
operations required to sort the array.

 

Input:

3
1 3
1 3 2
2 6
1 5 2 4 3 6
3 23
67890 56312 999999999 12345 23456
38927 45632 100345 98765 23456
87654 43278 23456 117654 321899
25432 54326 217435 26845 31782
33456 41234 56213

Output:

1 1
2 3
3 15

题意:

给定一个由n个数字组成的串,每次进行三步:

1、选择一个数字

2、将该数字从数组中删除

3、将该数字加到数组的最后

然后用这三步将一个无序的数组变成有序的,问最少需要的步数?

思路:

如果当前数字的后边有比它小的,说明这个数字不是排好序的,就把这个数字移动到数组的最后,对n后的字符重新排序,保证移动过去的字符都是有序的
注意,需要2倍的空间

CODE:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;

typedef long long LL;
#define memset(a,n) memset(a,n,sizeof(n))

LL a[2000+10];

int main()
{
    int t,n,num;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d %d",&num,&n);
        for(int i=0;i<n;i++)
            scanf("%lld",&a[i]);

        LL cnt=0;

        for(int i=0;i<n;i++)
        {
            for(int j=i+1;j<n+cnt;j++) // 数组之后添加了数字,下标也在变化
            {
                if(a[j]<a[i])
                {
                    cnt++;
                    a[n+cnt-1]=a[i];
                    sort(a+n,a+n+cnt);
                    break;
                }
            }
        }

        printf("%d %lld\n",num,cnt);
    }
}

 

4、A Rational Sequence (Take 3)

题目链接

题意:左子树的分子等于父亲的分子,分母等于父亲的分子分母之和;

   右子树的分子等于父亲的分子分母之和,分母等于父亲的分母;

思路:

数据量太大,用递归就行,每次递归它的父亲节点 ( n/2 )  (没想到用递归,就在那里利用树的性质各种推规律,尴了个尬)

CODE:

(1)、利用全局变量

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;

typedef long long LL;
#define memset(a,n) memset(a,n,sizeof(n))

LL sum=0;
LL a=1,b=1;

void F(LL n)
{
    if(n==1)
        return ;
    F(n/2);
    if(n%2==0)
    {
        sum=a+b;
        a=a;
        b=sum;
    }
    else
    {
        sum=a+b;
        a=sum;
        b=b;
    }
    return ;


}
int main()
{
    LL t,num,n;

    scanf("%lld",&t);
    while(t--)
    {
        a=1,b=1;
        scanf("%lld %lld",&num,&n);
        F(n);
        printf("%lld %lld/%d\n",num,a,b);
    }
}

(2)、利用结构体,每次递归返回结构体

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;

typedef long long LL;
#define memset(a,n) memset(a,n,sizeof(n))

struct NODE
{
    LL a;
    LL b;
}ans;

NODE F(LL n)
{
    NODE data,data1;
    if(n==1)
    {
        data.a=1;
        data.b=1;
        return data;
    }
    if(n%2==0)
    {
        data1=F(n/2);
        data.a=data1.a;
        data.b=data1.a+data1.b;
    }
    else
    {
        data1=F(n/2);
        data.b=data1.b;
        data.a=data1.a+data1.b;
    }
    return data;
}

int main()
{
    LL t,num,n;

    scanf("%lld",&t);
    while(t--)
    {
        scanf("%lld %lld",&num,&n);
        ans=F(n);
        printf("%lld %lld/%lld\n",num,ans.a,ans.b);
    }
}

 

5、

m-ary Partitions(m元划分)

Description
A partition of an integer n is a set of positive integers which sum to n, typically written in descending
order. For example:
10 = 4+3+2+1
A partition is m-ary if each term in the partition is a power of m. For example, the 3-ary partitions
of 9 are:
9
3+3+3
3+3+1+1+1
3+1+1+1+1+1+1
1+1+1+1+1+1+1+1+1
Write a program to find the number of m-ary partitions of an integer n.

Input
The first line of input contains a single decimal integer P, (1 ≤ P ≤ 1000), which is the number of data
sets that follow. Each data set should be processed identically and independently.
Each data set consists of a single line of input. The line contains the data set number, K, followed by
the base of powers, m, (3 ≤ m ≤ 100), followed by a space, followed by the integer, n, (3 ≤ n ≤ 10000),
for which the number of m-ary partitions is to be found.

Output
For each data set there is one line of output. The output line contains the data set number, K, a space,
and the number of m-ary partitions of n. The result should fit in a 32-bit unsigned integer.

Sample Input
5
1 3 9
2 3 47
3 5 123
4 7 4321
5 97 9999

Sample Output
1 5
2 63
3 75
4 144236
5 111

题意:

A partition is m-ary if each term in the partition is a power of m. ( power 幂 )

这句话就是题目的关键了,n是由 m 的 k(0<= k <= n^(1/m) )次方组成的

例如 m=3 n=9 时,9可以由 3^0 , 3^1 , 3^2 组成,就是样例中的情况,总共5种方法数

思路:完全背包的变形

完全背包的详解博客

(1)、首先求出 k的个数( m^k   0<= k <= n^(1/m) )  

2)、其次赋初值,任意的n都可以有 m^0 ( 1 ) 组成

(3)、状态转移方程

    dp [ j ] = dp [ j ] + dp [ j - m^k ] ;

               

 for(LL i=1;i<=cnt;i++)
 {
       LL data=pow(m,i);   //  data = m^k ;
       for(LL j=data;j<=n;j++) // data -n 之间的数都可以由 本身 - data 组成
            dp[j]+=dp[j-data];
 }

 

CODE:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;

typedef long long LL;
#define memset(a,n) memset(a,n,sizeof(n))

LL dp[10000+10];

int main()
{
    LL t,num,m,n;
    scanf("%lld",&t);

    while(t--)
    {
        LL cnt=0;
        scanf("%lld %lld %lld",&num,&m,&n);
        while(1)
        {
            if(pow(m,cnt)>n)
                break;
            cnt++;
        }

        for(LL i=0; i<=10000; i++)
            dp[i]=1;

        for(LL i=1;i<=cnt;i++)
        {
            LL data=pow(m,i);
            for(LL j=data;j<=n;j++)
                dp[j]+=dp[j-data];
        }

        printf("%lld %lld\n",num,dp[n]);



    }
}

 

6、Permutation Descent Counts

7787 Permutation Descent Counts
Given a positive integer, N, a permutation of order N is a one-to-one (and thus onto) function from
the set of integers from 1 to N to itself. If p is such a function, we represent the function by a list of
its values:
[p(1)p(2). . . p(N)]
For example,
[5 6 2 4 7 1 3] represents the function from {1 . . . 7} to itself which takes 1 to 5, 2 to 6, . . ., 7 to 3.
For any permutation p, a descent of p is an integer k for which p(k) > p(k + 1). For example, the
permutation [5 6 2 4 7 1 3] has a descent at 2(6 > 2) and 5(7 > 1).
For permutation p, des§ is the number of descents in p. For example, des([5624713]) = 2. The
identity permutation is the only permutation with des§ = 0. The reversing permutation with p(k) =
N + 1 − k is the only permutation with des§ = N − 1.
The permutation descent count (PDC) for given order N and value v is the number of permutations
p of order N with des§ = v. For example:
P DC(3, 0) = 1{[123]}
P DC(3, 1) = 4{[132], [213], [231], 312]}
P DC(3, 2) = 1{[321]}


Write a program to compute the PDC for inputs N and v. To avoid having to deal with very large
numbers, your answer (and your intermediate calculations) will be computed modulo 1001113.
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 should be processed identically and independently.
Each data set consists of a single line of input. It contains the data set number, K, followed by the
integer order, N (2 ≤ N ≤ 100), followed by an integer value, v (0 ≤ v ≤ N − 1).
Output
For each data set there is a single line of output. The single output line consists of the data set number,
K, followed by a single space followed by the PDC of N and v modulo 1001113 as a decimal integer.
Sample Input
4
1 3 1
2 5 2
3 8 3
4 99 50
Sample Output
1 4
2 66
3 15619
4 325091

题意:

解释题目中给定的样例

[5 6 4 2 7 1 3] 类似逆序对是2(6>4  7>1)  (其实也不是正规的逆序对,是前后两个比较大小,如果前一个大于后一个,成为类似逆序对-自己起的名字hhh)

给定n m 求 n 个长度,类似逆序数是 m 的方法数有几种

思路:看完题意就知道是 dp 题

状态转移方程 dp[ i ][ j ]=dp[ i-1 ][ j ]*( j+1 )+dp[ i-1 ][ j-1 ]*( i-j );

 


 

解释dp 数组,i代表长度,也是每一次要插入的数字,j代表的是类似逆序的数目

dp[i][j] 是由上一个长度推出来,类似逆序数可以是 j ,也可以是 j-1

把i插入到i-1个数目之间有i个方法(插空法)

(1)、当是j的时候,代表类似逆序数目没有增加,把i插入这i-1个空格中只有两种情况

    插到最后  +  在逆序数目之间插入也不改变总的类似逆序数目(4 3 6 插入7,可以在6之后,也可以在4 3 之间插入不改变类似逆序数的数目)

    方法数是j+1 种 (j代表逆序数的对数,1代表插入到最后)

(2)、当是j-1的时候,代表类似逆序数的数目只加了1,把i插到i-1个空格中有两种情况

    插到开始  +  在不成逆序数的对数之间插入(4 1 3 2 插入5,可以把5插入到4之前,也可以插入到1 5 3,这两种方法只增加了一个逆序数,不能)

    方法数:不成逆序数的数目为 i-(j-1) (此时有j-1对,那么i-(j-1)是不成逆序数的空格数,比如说 4 1 3 2 ,此时逆序数是2,想增加1可以在4之前,1 3 之间,2之后插入,但是在最后插入的话不能改变类似逆序数的数目,所以方法数是 i-(j-1)-1=i-j )

 


需要对结果求余,所以利用同余定理

 

CODE:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;

typedef long long LL;
#define memset(a,n) memset(a,n,sizeof(n))
#define mod 1001113

int dp[105][105];

int main()
{
    int t,num,x,y;
    scanf("%d",&t);

    for(int i=2;i<=101;i++)
        dp[i][0]=1;

    for(int i=2;i<=101;i++)
        for(int j=0;j<=i-1;j++)
    {
        if(j==i-1||j==0)
            dp[i][j]=1;
        else
            dp[i][j]=((dp[i-1][j]*(j+1))%mod+(dp[i-1][j-1]*(i-j))%mod)%mod;
    }
    while(t--)
    {
        scanf("%d %d %d",&num,&x,&y);
        printf("%d %d\n",num,dp[x][y]);
    }
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值