2016A组
A
试题来源:http://oj.hzjingma.com/p/7000?view=classic
【问题描述】
某君新认识一网友。
当问及年龄时,他的网友说:
“我的年龄是个2位数,我比儿子大27岁,
如果把我的年龄的两位数字交换位置,刚好就是我儿子的年龄”
请你计算:网友的年龄一共有多少种可能情况?
提示:30岁就是其中一种可能哦.
请填写表示可能情况的种数。
【答案提交】
你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
题解:
枚举网友的年龄即可
#include<bits/stdc++.h>
using namespace std;
int rs(int x){
int t=x;
//int que[5],head=0,tail=0;
int sum=0;
do{
int d=t%10;
t/=10;
sum=sum*10+d;
//que[tail++]=d;
}while(t>0);
// for(int i=0;i<tail;i++){
// sum=sum*10+que[i];
// }
return sum;
}
int main(){
int cnt=0;
for(int i=27;i<=100;i++){
int son=i-27;
if(rs(i)==son){
cnt++;
cout<<i<<endl;
}
}
cout<<cnt;
}
B
试题来源:http://oj.hzjingma.com/p/7001?view=classic
【问题描述】
某君从某年开始每年都举办一次生日party,并且每次都要吹熄与年龄相同根数的蜡烛。
现在算起来,他一共吹熄了236根蜡烛。
请问,他从多少岁开始过生日party的?
请填写他开始过生日party的年龄数。
【答案提交】
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
题解:
枚举这个人开始过party的年龄,过生日的年数
#include<bits/stdc++.h>
using namespace std;
int main(){
int s=1;
int ans=0;
for(s=1;s<=100;s++){
int age=1;
int sum=0;
for(int k=1;k<=100;k++){
int sd=(2*s+k-1)*k/2;
if(sd==236){
ans=s;
cout<<k<<endl;
goto end;
}
}
}
end:;
cout<<ans;
}
C
【问题描述】
如下的10个格子
填入0~9的数字。要求:连续的两个数字不能相邻。
(左右、上下、对角都算相邻)
一共有多少种可能的填数方案?
请填写表示方案数目的整数。
【答案提交】
你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
题解:
dfs搜索,对每一个格子枚举所有的可能,然后检验可行性
也可以9重循环逐个测试
#include<bits/stdc++.h>
using namespace std;
int a[3][4]={0};
int cnt=0;
bool book[3][4]={0};
bool vis[10]={0};
bool check(int i,int x,int y){
int nexty[8][2]={{0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};
for(int k=0;k<8;k++){
int tx=x+nexty[k][0];
int ty=y+nexty[k][1];
if(tx<0||tx>2||ty<0||ty>3) continue;
if(book[tx][ty]==1){
if(abs(a[tx][ty]-i)==1){
return false;
}
}
}
return true;
}
void dfs(int x,int y){
if(x==2&&y==3){
cnt++;
return;
}
if(y>3){
x++,y=0;
if(x>2) return;
}
for(int i=0;i<=9;i++){
if(vis[i]==0&&check(i,x,y)){
book[x][y]=1;
vis[i]=1;
a[x][y]=i;
dfs(x,y+1);
book[x][y]=0;
vis[i]=0;
}
}
}
int main(){
dfs(0,1);
cout<<cnt;
}
D代码填空题,不写
E代码填空题,不写
F
【问题描述】
现在小学的数学题目也不是那么好玩的。
看看这个寒假作业:
每个方块代表1~13中的某一个数字,但不能重复。
比如:
6 + 7 = 13
9 - 8 = 1
3 * 4 = 12
10 / 2 = 5
以及:
7 + 6 = 13
9 - 8 = 1
3 * 4 = 12
10 / 2 = 5
就算两种解法。(加法,乘法交换律后算不同的方案)
你一共找到了多少种方案?
请填写表示方案数目的整数。
【答案提交】
你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
题解:
开一个长度为12的数组,逐个填数,每个格子枚举9种情况
注意当枚举到第3,6,9,12个格子的时候,需要调用check函数检验当前的这个式子的正确性(剪枝)
#include<bits/stdc++.h>
using namespace std;
int a[14];
bool book[14];
int cnt=0;
bool check(int step){
if(step==3){
if(a[1]+a[2]==a[3]) return 1;
}else if(step==6){
if(a[4]-a[5]==a[6]) return 1;
}else if(step==9){
if(a[7]*a[8]==a[9]) return 1;
}else if(step==12){
if(a[11]*a[12]==a[10]) return 1;
}
return 0;
}
void dfs(int step){
if(step==13){
cnt++;
return ;
}
for(int i=1;i<=13;i++){
if(!book[i]){
a[step]=i;
if(step==3||step==6||step==9||step==12){
if(check(step)){
book[i]=1;
dfs(step+1);
book[i]=0;
}
}else{
book[i]=1;
dfs(step+1);
book[i]=0;
}
}
}
}
int main(){
dfs(1);
cout<<cnt;
}
G
【问题描述】
如图1, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,图2和图3中,粉红色所示部分就是合格的剪取。
图1
图2
图3
请你计算,一共有多少种不同的剪取方法。
请填写表示方案数目的整数。
【答案提交】
你提交的应该是一个整数。不要填写任何多余的内容或说明性的文字。
题解:
每次剪下的邮票可以看错是一个连通块,我们可以枚举一次需要剪下哪些格子,然后检测这些格子的连通性(连通块个数),如果为1,说明它们必定连通,ans++
#include<bits/stdc++.h>
using namespace std;
bool cho[12]={0,0,0,0,0,0,0,1,1,1,1,1};//记录哪些数字需要被选择
int mp[3][4];
void dfs(int x,int y){
mp[x][y]=0;
int nxt[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
for(int k=0;k<4;k++){
int tx=x+nxt[k][0];
int ty=y+nxt[k][1];
if(tx<0||tx>2||ty<0||ty>3) continue;
if(mp[tx][ty]){
dfs(tx,ty);
}
}
}
int main(){
int ans=0;
do{
memset(mp,0,sizeof(mp));
int k=0;
int cnt=0;//连通块个数
for(int i=0;i<3;i++){
for(int j=0;j<4;j++){
if(cho[k]){
mp[i][j]=1;
}
k++;
}
}
for(int i=0;i<3;i++){
for(int j=0;j<4;j++){
if(mp[i][j]){
cnt++;
dfs(i,j);
}
k++;
}
}
if(cnt==1) ans++;
}while(next_permutation(cho,cho+12));
cout<<ans;
}
H
【问题描述】
四平方和定理,又称为拉格朗日定理:
每个正整数都可以表示为至多4个正整数的平方和。
如果把0包括进去,就正好可以表示为4个数的平方和。
比如:
5 = 0^2 + 0^2 + 1^2 + 2^2
7 = 1^2 + 1^2 + 1^2 + 2^2
对于一个给定的正整数,可能存在多种平方和的表示法。
要求你对44个数排序:
0 <= a <= b <= c <= d
并对所有的可能表示法按 a,b,c,d为联合主键升序排列,最后输出第一个表示法
输入
程序输入为一个正整数N (N<5000000)
输出
要求输出44个非负整数,按从小到大排序,中间用空格分开
样例
输入
5
输出
0 0 1 2
输入
12
输出
0 2 2 2
输入
773535
输出
1 1 267 838
题解:直接枚举,注意四重循环可以优化为三重循环,求幂次那里可以手写一个快速幂
#include<iostream>
using namespace std;
typedef long long ll;
ll qpow(int x, int y);
int main() {
ios::sync_with_stdio(0);
int n;
while (cin >> n) {
for (int i = 0;; i++) {
ll s1 = qpow(i, 2);
if (s1 > n||i>n) {
break;
}
for (int j = i;; j++) {
ll s2 = qpow(j, 2);
if (s2 > n || j > n) {
break;
}
for (int k = j;; k++) {
ll s3 = qpow(k, 2);
if (s3 > n || k > n){
break;
}
ll s4 = n - s1 - s2 - s3;
if (s4 < 0) {
break;
}
ll tmp = sqrt(s4);
if (tmp < k) {
break;
}
if (tmp*tmp==s4&&s4 <= n&&s4>=0) {
cout << i << " " << j << " " << k << " " << tmp << endl;
goto A;
}
}
}
}
A:;
}
}
ll qpow(int x, int y) {
ll res = 1;
while (y) {
if (y & 1) {
res = res * x;
}
y = y >> 1;
x = x * x;
}
return res;
}
I
X星球的考古学家发现了一批古代留下来的密码。
这些密码是由A、B、C、D 四种植物的种子串成的序列。
仔细分析发现,这些密码串当初应该是前后对称的(也就是我们说的镜像串)。
由于年代久远,其中许多种子脱落了,因而可能会失去镜像的特征。
你的任务是:
给定一个现在看到的密码串,计算一下从当初的状态,它要至少脱落多少个种子,才可能会变成现在的样子。
输入
输入一行,表示现在看到的密码串(长度不大于1000)
输出
要求输出一个正整数,表示至少脱落了多少个种子。
样例
输入复制
ABCBA
输出复制
0
输入复制
ABDCDCBABC
输出复制
3
题解:
该题属于“添加多少个字符使得字符串镜像对称”题型,一般可以将字符串逆转然后和原串取最大公共子序列,再用原串长度减去最大公共子序列长度
需要的知识:
LCS(最长公共子序列的dp解法)
#include<bits/stdc++.h>
using namespace std;
string a,b;
int f[1005][1005];
int main(){
cin>>b;
a=b;
reverse(b.begin(),b.end());
for(int i=1;i<=a.length();i++){
for(int j=1;j<=b.length();j++){
if(a[i-1]==b[j-1]) f[i][j]=f[i-1][j-1]+1;
else f[i][j]=max(f[i-1][j],f[i][j-1]);
}
}
cout<<a.length()-f[a.length()][b.length()];
}