20170402"尚学堂杯"哈尔滨理工大学第七届程序设计竞赛ABCDFG题解

来源:互联网 发布:后窗知乎 编辑:程序博客网 时间:2024/04/25 18:30

第一次参加个人赛

想着自己太辣稽肯定不能拿最佳新人

最后A了3题

实在是太辣稽了

A题 组合数取模 因为以为是很难的数学题就没做 我好智障...

B题 思维题 一开始太不谨慎了wa了几发...

C题 走台阶问题 因为没意识到数组初始赋值错了 一直错到比赛结束都不知道怎么回事 我好智障...

D题 简单Floyd 比赛时没读懂题意 赛后知道是Floyd实在是好气啊(捂脸痛哭)

F题 简单字符串模拟

G题 二进制 我竟然水过了

_______________________________________________________

Astonishing Combinatorial NumberTime Limit: 8000 MSMemory Limit: 512000 KTotal Submit: 56(11 users)Total Accepted: 14(9 users)Rating:Special Judge: NoDescription

The combinatorial number CmnCnm in combinatorics, where it gives the number of the ways, disregarding order,

the m objects can be chosen from among n objects; more formally, the number of m-element subsets (or m-combinations)

of an n-element set.

Now, there's a simple problem about this number:

For three given number n, m and k, how many pairs of (i, j) will make the equation A.a be true. (0 <= i <= n, 0 <= j <= min(i, m))

Equation A.1:

Cjimodk=0Cijmodk=0

Input

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases.

For each test case:
The first line contains two integers t(1<=t<=10^4) and k(1<=k<=30).
Each of the next t lines contains two integers n(1<=n<=2000) and m(1<=m<=2000) .


OutputEach test case should contain t lines. Each line has an integer indicate the answer of the problem.

Sample Input2
1 2
3 3
2 5
4 5
6 7Sample Output

1

0

7

HintIn first test case, onlyC12=2C21=2 is multiple of 2.Source"尚学堂杯"哈尔滨理工大学第七届程序设计竞赛题意:给出n m k 求Cij mod k的方案数


思路:首先预处理(打表),然后统计方案数。

1

1  1

1  2  1

1  3  3  1

...................

#include#include#includeusing namespace std;int c[2005][2005];int main(){int T;int t,k;while(~scanf("%d",&T))while(T--){scanf("%d%d",&t,&k);memset(c,0,sizeof(c));c[0][0]=1%k;for(int i=1;i<2005;i++){c[i][0]=1%k;c[i][i]=1%k;}for(int i=1;i<2005;i++)for(int j=1;j


Blind FatherTime Limit: 1000 MSMemory Limit: 512000 KTotal Submit: 131(57 users)Total Accepted: 66(54 users)Rating:Special Judge: NoDescription

Mr. Leng, who is the predominately inheritor of buried-love family (One of the most vogue families during your primary school maybe, anyway, this is unimportant), has such cool, cooler and coolest temperament. But, only a good ACMer can be the real leader, in other words, be admitted as a successor.

One day, a problem come to Mr. Leng 's father about carpentry. There are N pieces of planks upright the ground in one line. Each one width 1 and height uncertain. His father wants to cut some of them and then get a rectangle. How the biggest rectangle does him can make? It too difficult to his father to solve the problem, but it is really easy for Mr. Leng. So do you. Please surmount the problem as soon as you can.

Ps: You can't move or change the posture or position of any planks.

Input

There are multiple cases. In each cases, the first line only contains an integer N,

means the number of the planks. And the second line contains N numbers, means the height of N planks one by one.

1<=N<=10000



OutputPlease output the biggest rectangle that Mr. Leng 's father can get.Sample Input
310 6 10
Sample Output18Hint样例图形Source"尚学堂杯"哈尔滨理工大学第七届程序设计竞赛题意:给出n个木板(可当成矩形) 选取连续的一部分木板(可以是一块或多块木板)经过切割后(有可能不用切割)得到一个矩形 求可得到的矩形的最大值


思路:暴力搜时间复杂度为O(n^2)会超时

            在遍历的时候以当前木板为一段连续木板中最短的一块木板,以此为中心往左右遍历搜索最长的连续木板,因为切割木板的话一定是以最短的木板为基准对其他木板进行             切割,所以每次只要遍历到长度大于等于当前木板的木板就行了。


#include<cstdio>#include<iostream>using namespace std;int a[10005];int main(){   int n;   while(~scanf("%d",&n))   {      for (int i=1;i<=n;i++)        scanf("%d",&a[i]);      int m=0;      for (int i=1;i<=n;i++)      {         int l=i-1,r=i+1;         int ins=1;         while(l>=1)            if (a[i]<=a[l]) { l--; ins++; }            else break;         while(r<=n)            if (a[i]<=a[r]) { r++; ins++; }            else break;        m=max(m,ins*a[i]);      }      printf("%d\n",m);   }}


Collection GameTime Limit: 1000 MSMemory Limit: 128000 KTotal Submit: 123(50 users)Total Accepted: 54(47 users)Rating:Special Judge: NoDescriptionPOI and POJ are pair of sisters, one is a master in “Kantai Collection”, another is an excellent competitor in ACM programming competition. One day, POI wants to visit POJ, and the pace that between their homes is made of square bricks. We can hypothesis that POI’s house is located in the NO.1 brick and POJ’s house is located in the NO.n brick. For POI, there are three ways she can choose to move in every step, go ahead one or two or three bricks. But some bricks are broken that couldn’t be touched. So, how many ways can POI arrive at POJ’s house?

Input

There are multiple cases.

In each case, the first line contains two integers N(1<=N<=10000) and M (1<=M<=100), respectively represent the sum of bricks, and broke bricks. Then, there are M number in the next line, the K-th number a[k](2<=a[k]<=n-1) means the brick at position a[k] was broke.

OutputPlease output your answer P after mod 10007 because there are too many ways.Sample Input

5 1

3

Sample Output3Source"尚学堂杯"哈尔滨理工大学第七届程序设计竞赛题意:有n个台阶,有m个坏了,求走上第n个台阶的方案数(从第一个台阶开始走)


思路:只要把坏了的台阶的步数赋值为0就可以了

           递推公式f(x)=f(x-1)+f(x-2)+f(x-3)

#include<cstdio>#include<cstring>#define mod 10007int f[10005];int v[10005];int main(){   int n,m;   int a;   while(~scanf("%d%d",&n,&m))   {      memset(v,0,sizeof(v));      f[2]=1;      f[3]=2; f[4]=4;      for (int i=1;i<=m;i++)      {        scanf("%d",&a);        v[a]=1;      }      f[4]-=( (v[2]+v[3])==0 ? 0 : ( (v[2]+v[3])==1?2:3 ) );      f[3]-=( v[2]?f[2]:0 );      for (int i=5;i<=n;i++)      {         if (v[i]) { f[i]=0; continue; }         f[i]=( ( v[i-1]?0:f[i-1] ) + ( v[i-2]?0:f[i-2] ) + ( v[i-3]?0:f[i-3] ) )%mod;      }      printf("%d\n",f[n]%mod);   }}

Distinct Package ManagerTime Limit: 1000 MSMemory Limit: 512000 KTotal Submit: 124(32 users)Total Accepted: 35(23 users)Rating:Special Judge: NoDescription

On Linux or OSX, we can install software by package manager. For example, apt-get in Ubuntu/Debian, yum in Fedora/CentOS and brew in OSX. All of them are great software-package manager.

You determined to design your own software-package manager. The inevitable thing is you should solve dependences of these software-packages.

• If package A depends package B, you should install package B before installing package A.

• If you want to uninstall package B, then you must uninstall package A.

Now, you already know all the dependences of all these software-packages. You can assume that 0-package don’t depend any other package. And all dependence-relationship won’t form a circle. Of course, no package depend itself.

Your uses want to know how many packages’ install state will be changed when installing or uninstalling a package.

NOTE: Install an installed package and uninstall an uninstalled package won’t change any packages’ state.


InputThere are multiple test cases. The first line of input contains an integer T, indicating the number of test cases.

The first line of each test cases contains an integer n(1<=n<=100), indicating the number of software-packages.

For each software-package(except 0-package) contains two lines, the first line contains an integer mi, indicating the number of dependences of i-package. The next mi integers indicating the serial numbers of dependences.

The next line contains an integer q(1<=q<=200), indicating the number of queries.

Each of the next q liens contains a string s and an integer k, indicating the action and serial number of software-package. s must be one of "install" and "uninstall".

OutputFor each query, output a line contains the number of changed packages.Sample Output
12102install 1uninstall 0
Hint
22
Source"尚学堂杯"哈尔滨理工大学第七届程序设计竞赛题意:给出软件包的依赖关系 求安装或卸载包所需要的操作次数


思路:根据依赖关系A依赖于B可得,安装时先安装A在安装B 卸载时先卸载B再卸载A

           要注意的是已安装的不用安装,已卸载(或根本没安装)的不用卸载即用一个数组记录包的安装状态(安装或未安装)最后遍历求操作总数

           (要是能读懂题意的话 我。。)

#include<cstdio>#include<cstring>using namespace std;int a[105][105];int v[105];int main(){   int t;   int n,q;   while(~scanf("%d",&t))   while(t--)   {      scanf("%d",&n);      memset(a,0,sizeof(a));      memset(v,0,sizeof(v));      for (int i=1;i<=n-1;i++)      {         int x,y;         scanf("%d",&x);         for (int j=1;j<=x;j++)         {            scanf("%d",&y);            a[y][i]=1;         }      }      for (int i=0;i<=100;i++)        for (int j=0;j<=100;j++)          for (int k=0;k<=100;k++)           if (a[j][i]==1&&a[i][k]==1)             a[j][k]=1;      scanf("%d",&q);      for (int i=1;i<=q;i++)      {         char op[15];         int x;         scanf("%s%d",op,&x);         if (op[0]=='i')         {            if (v[x]) { puts("0"); continue; }            v[x]=1;            int num=0;            for (int j=0;j<=100;j++)             if (a[j][x]==1&&!v[j]) num++,v[j]=1;            printf("%d\n",num+1);         }         if (op[0]=='u')         {            if (!v[x]) { puts("0"); continue; }            v[x]=0;            int num=0;            for (int j=0;j<=100;j++)             if (a[x][j]==1&&v[j]) num++,v[j]=0;            printf("%d\n",num+1);         }      }   }}

Final Ugly EnglishTime Limit: 1000 MSMemory Limit: 32768 KTotal Submit: 146(58 users)Total Accepted: 76(56 users)Rating:Special Judge: NoDescription

ACM twist-toy encountered such a problem in the work, this article, to ensure that this article only lowercase letters

and spaces, please send the articles in each word inverted output, such as "hello world this is an competition". You

should output "olleh dlrow siht si na noititepmoc".

Input

A group of data, each line of data input from the lower case letters and spaces of the article, the length of not more than

one thousand

OutputOutput a line for each word after the reversal of the article.Sample Inputhello world this is an competitionSample Outputolleh dlrow siht si na noititepmocSource"尚学堂杯"哈尔滨理工大学第七届程序设计竞赛题意:看输入输出就知道了......


思路:简单模拟


#include<cstdio>#include<cstring>#include<iostream>#include<queue>#include<stack>#include<map>#include<algorithm>#define M(x) memset(x,0,sizeof(x))#define N 100005#define inf 0x3f3f3f#define For(n) for (int i=1;i<=n;i++)using namespace std;int main(){   char a[1005],b[1005];   M(a); M(b);   while(gets(a))   {      int n=strlen(a);      int p=0;      for (int i=0;i<=n-1;i++)      {         if (a[i]>='a'&&a[i]<='z')            b[p++]=a[i];         if (a[i]==' ')         {            reverse(b,b+p);            p=0;            printf("%s",b);            putchar(' ');            M(b);         }      }      if (a[n-1]>='a'&&a[n-1]<='z')      {        reverse(b,b+p);        printf("%s\n",b);        M(b);      }   }}

Great AtmTime Limit: 1000 MSMemory Limit: 32768 KTotal Submit: 178(34 users)Total Accepted: 63(30 users)Rating:Special Judge: NoDescriptionAn old story said the evil dragon wasn’t evil at all, only bewitched, and now that the riddles were solved it was proving to be as kind as its new master.
A powerful warrior Atm is going to solve the riddles. First, he should beat the evil wizard. The road from Atm’s castle to wizard’s lab is filled with magic traps. The magic trap will affect Atm’s combat effectiveness.
Atm’s combat effectiveness can be considered as an integer. Effect of magic trap can be considered as mathematical operation. The three kinds of magic traps correspond to three kind of bit operation. (AND, OR and XOR)
Atm can adjust his equipment to change his initial combat effectiveness from 0 to m (include 0 and m). He wants when he arrives the wizard’s lab, his combat effectiveness can be maximum.InputThere are multiple test cases.
For each test cases:
The first line contains two integers n(1<=n<=10^5) and m(1<=m<=10^9), indicating the number of magic traps and the maximum of initial combat effectiveness.
Each of the next n lines contains a string and an integer, indicating the bit operation. The string will be “AND”, “OR” or “XOR” correspond to AND operation (&), OR operation (|) or XOR operation (^). The integer t(1<=t<=10^9) is second operand in the operation.

OutputFor each test cases, a line contains an integer, indicatingthe maximum combat effectiveness when he arrives the wizard's lab.Sample Input3 10
AND 5
OR 6
XOR 7Sample Output1Source"尚学堂杯"哈尔滨理工大学第七届程序设计竞赛题意:给出一个数m,m可以从0~m变化(不定值),求m经过一系列位运算后的最大值


思路:把m分为奇偶数两种情况,然后水过,经测试这种做法不严谨且有bug

           学长们的严谨做法是用二进制计算 求出答案x(假设最大值为x)的每一个二进制位的最大值(0或1)最终得出答案


#include<cstdio>#include<iostream>using namespace std;int main(){   int n;   long long m;   while(~scanf("%d%lld",&n,&m))   {      long long ma=m-1;      for (int i=1;i<=n;i++)      {         char op[4];         long long num;         scanf("%s%lld",op,&num);         if (op[0]=='A') m&=num,ma&=num;         if (op[0]=='O') m|=num,ma|=num;         if (op[0]=='X') m^=num,ma^=num;      }      printf("%lld\n",max(m,ma));   }}


1 0
原创粉丝点击