20170402"尚学堂杯"哈尔滨理工大学第七届程序设计竞赛ABCDFG题解
2017-04-10 19:16
330 查看
第一次参加个人赛
想着自己太辣稽肯定不能拿最佳新人
最后A了3题
实在是太辣稽了
A题 组合数取模 因为以为是很难的数学题就没做 我好智障...
B题 思维题 一开始太不谨慎了wa了几发...
C题 走台阶问题 因为没意识到数组初始赋值错了 一直错到比赛结束都不知道怎么回事 我好智障...
D题 简单Floyd 比赛时没读懂题意 赛后知道是Floyd实在是好气啊(捂脸痛哭)
F题 简单字符串模拟
G题 二进制 我竟然水过了
_______________________________________________________
题意:给出n m k 求Cij mod k的方案数
思路:首先预处理(打表),然后统计方案数。
1
1 1
1 2 1
1 3 3 1
...................
#include
#include
#include
using 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[0]=1%k;
c[i][i]=1%k;
4000
}
for(int i=1;i<2005;i++)
for(int j=1;j[i]
题意:给出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);
}
}
题意:有n个台阶,有m个坏了,求走上第n个台阶的方案数(从第一个台阶开始走)
思路:只要把坏了的台阶的步数赋值为0就可以了
递推公式f(x)=f(x-1)+f(x-2)+f(x-3)
题意:给出软件包的依赖关系 求安装或卸载包所需要的操作次数
思路:根据依赖关系A依赖于B可得,安装时先安装A在安装B 卸载时先卸载B再卸载A
要注意的是已安装的不用安装,已卸载(或根本没安装)的不用卸载即用一个数组记录包的安装状态(安装或未安装)最后遍历求操作总数
(要是能读懂题意的话 我。。)
题意:看输入输出就知道了......
思路:简单模拟
#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);
}
}
}
题意:给出一个数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));
}
}
想着自己太辣稽肯定不能拿最佳新人
最后A了3题
实在是太辣稽了
A题 组合数取模 因为以为是很难的数学题就没做 我好智障...
B题 思维题 一开始太不谨慎了wa了几发...
C题 走台阶问题 因为没意识到数组初始赋值错了 一直错到比赛结束都不知道怎么回事 我好智障...
D题 简单Floyd 比赛时没读懂题意 赛后知道是Floyd实在是好气啊(捂脸痛哭)
F题 简单字符串模拟
G题 二进制 我竟然水过了
_______________________________________________________
Astonishing Combinatorial Number | ||||||
| ||||||
Description | ||||||
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) . | ||||||
Output | ||||||
Each test case should contain t lines. Each line has an integer indicate the answer of the problem. | ||||||
Sample Input | ||||||
2 1 2 3 3 2 5 4 5 6 7 | ||||||
Sample Output | ||||||
1 0 7 | ||||||
Hint | ||||||
In first test case, onlyC12=2C21=2 is multiple of 2. | ||||||
Source | ||||||
"尚学堂杯"哈尔滨理工大学第七届程序设计竞赛 |
思路:首先预处理(打表),然后统计方案数。
1
1 1
1 2 1
1 3 3 1
...................
#include
#include
#include
using 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[0]=1%k;
c[i][i]=1%k;
4000
}
for(int i=1;i<2005;i++)
for(int j=1;j[i]
Blind Father | ||||||
| ||||||
Description | ||||||
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 | ||||||
Output | ||||||
Please output the biggest rectangle that Mr. Leng 's father can get. | ||||||
Sample Input | ||||||
3 10 6 10 | ||||||
Sample Output | ||||||
18 | ||||||
Hint | ||||||
样例图形 | ||||||
Source | ||||||
"尚学堂杯"哈尔滨理工大学第七届程序设计竞赛 |
思路:暴力搜时间复杂度为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 Game | ||||||
| ||||||
Description | ||||||
POI 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. | ||||||
Output | ||||||
Please output your answer P after mod 10007 because there are too many ways. | ||||||
Sample Input | ||||||
5 1 3 | ||||||
Sample Output | ||||||
3 | ||||||
Source | ||||||
"尚学堂杯"哈尔滨理工大学第七届程序设计竞赛 |
思路:只要把坏了的台阶的步数赋值为0就可以了
递推公式f(x)=f(x-1)+f(x-2)+f(x-3)
#include<cstdio> #include<cstring> #define mod 10007 int 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 Manager | ||||||
| ||||||
Description | ||||||
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. Th f221 e 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. | ||||||
Input | ||||||
There 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". | ||||||
Output | ||||||
For each query, output a line contains the number of changed packages. | ||||||
Sample Output | ||||||
1 2 1 0 2 install 1 uninstall 0 | ||||||
Hint | ||||||
2 2 | ||||||
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 English | ||||||
| ||||||
Description | ||||||
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 | ||||||
Output | ||||||
Output a line for each word after the reversal of the article. | ||||||
Sample Input | ||||||
hello world this is an competition | ||||||
Sample Output | ||||||
olleh dlrow siht si na noititepmoc | ||||||
Source | ||||||
"尚学堂杯"哈尔滨理工大学第七届程序设计竞赛 |
思路:简单模拟
#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 Atm | ||||||
| ||||||
Description | ||||||
An 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. | ||||||
Input | ||||||
There 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. | ||||||
Output | ||||||
For each test cases, a line contains an integer, indicating the maximum combat effectiveness when he arrives the wizard's lab. | ||||||
Sample Input | ||||||
3 10 AND 5 OR 6 XOR 7 | ||||||
Sample Output | ||||||
1 | ||||||
Source | ||||||
"尚学堂杯"哈尔滨理工大学第七届程序设计竞赛 |
思路:把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));
}
}
相关文章推荐
- "尚学堂杯"哈尔滨理工大学第七届程序设计竞赛 F.Final Ugly English(字符串处理)
- "尚学堂杯"哈尔滨理工大学第七届程序设计竞赛——Hrbust2326 Blind Father
- "尚学堂杯"哈尔滨理工大学第七届程序设计竞赛 G(2331) Great Atm(二进制)(思路)
- "尚学堂杯"哈尔滨理工大学第七届程序设计竞赛 D 2328 Distinct Package Manager
- "尚学堂杯"哈尔滨理工大学第七届程序设计竞赛 C.Collection Game(DP)
- "尚学堂杯"哈尔滨理工大学第七届程序设计竞赛 G(2331) Great Atm(二进制)(思路)
- HRBUST 2326 Blind Father "尚学堂杯"哈尔滨理工大学第七届程序设计竞赛
- "尚学堂杯"哈尔滨理工大学第七届程序设计竞赛 G(2331) Great Atm(二进制)(思路)
- HRBUST 2327 Collection Game "尚学堂杯"哈尔滨理工大学第七届程序设计竞赛
- "尚学堂杯"哈尔滨理工大学第七届程序设计竞赛 G(2331) Great Atm(二进制)(思路)
- "尚学堂杯"哈尔滨理工大学第七届程序设计竞赛 G(2331) Great Atm(二进制)(思路)
- "尚学堂杯"哈尔滨理工大学第七届程序设计竞赛 G(2331) Great Atm(二进制)(思路)
- "尚学堂杯"哈尔滨理工大学第七届程序设计竞赛 hrbust 2331 Great Atm
- "尚学堂杯"哈尔滨理工大学第七届程序设计竞赛 G(2331) Great Atm(二进制)(思路)
- "尚学堂杯"哈尔滨理工大学第七届程序设计竞赛 B.Blind Father【思维枚举】
- "尚学堂杯"哈尔滨理工大学第七届程序设计竞赛 G(2331) Great Atm(二进制)(思路)
- "尚学堂杯"哈尔滨理工大学第七届程序设计竞赛 C.Collection Game【递推】
- "尚学堂杯"哈尔滨理工大学第七届程序设计竞赛D--Distinct Package Manager
- "尚学堂杯"哈尔滨理工大学第七届程序设计竞赛 G(2331) Great Atm(二进制)(思路)
- "尚学堂杯"哈尔滨理工大学第七届程序设计竞赛 B Blind Father(单调栈)+G Great Atm(二进制)