A
题目
今天蒜头君带着花椰妹和朋友们一起聚会,当朋友们问起年龄的时候,蒜头君打了一个哑谜(毕竟年龄是女孩子的隐私)说:“我的年龄是花椰妹年龄个位数和十位数之和的二倍”。
花椰妹看大家一脸懵逼,就知道大家也不知道蒜头君的年龄,便连忙补充道:“我的年龄是蒜头君个位数和十位数之和的三倍”。
请你计算:蒜头君和花椰妹年龄一共有多少种可能情况?
提醒:两位的年龄都是在 [10,100)[10,100) 这个区间内。
代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
int ans=0;
for(int i=10;i<100;i++)
{
int m=2*(i%10+i/10);
int n=0;
if(m>=10&&m<100)
{
n=3*(m%10+m/10);
if(n==i)
ans++;
}
}
printf("%d",ans);
return 0;
}
遍历10~100,假设花椰妹年龄为i,根据花椰妹年龄求出蒜头君年龄,在判断是否符合题意即可。
B
题目
蒜头君今天回到了老家的大宅院,老家的灯还是那中拉线的灯(拉一次为亮,再拉一次就灭),蒜头君觉得无聊。把 1000 盏灯 3 的倍数拉了一次,5 的倍数拉了一次,7的倍数拉了一次(灯得的编号从 1-1000,灯的初始状态都是亮的)。这个时候蒜头君在想还剩下几盏灯还在亮着?
提示:请不要输出多余的符号
代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
int ans=0;
int l[1005];
for(int i=0;i<1005;i++)
l[i]=1;
for(int i=0;i<1000;i++)
{
if(i%3==0)
{
if(l[i]==0)
l[i]=1;
else
l[i]=0;
}
if(i%5==0)
{
if(l[i]==0)
l[i]=1;
else
l[i]=0;
}
if(i%7==0)
{
if(l[i]==0)
l[i]=1;
else
l[i]=0;
}
}
for(int i=0;i<1000;i++)
{
if(l[i]==1)
ans++;
}
printf("%d",ans);
return 0;
}
遍历1~1000直接模拟即可
C
题目
最近蒜头君喜欢上了U型数字,所谓U型数字,就是这个数字的每一位先严格单调递减,后严格单调递增。比如 212 就是一个U型数字,但是 333, 98, 567, 31313,就是不是U型数字。
现在蒜头君问你,[1,100000]有多少U型数字?
提示:请不要输出多余的符号。
代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
int l[10];
int ans=0;
for(int i=101;i<100000;i++)
{
memset(l,0,sizeof(l));
int j=0;
int a=i;
while(a!=0)
{
l[j++]=(a%10);
a/=10;
}//printf("%d\n",j);
int flag=0,flag1=0,flag2=0;
for(int k=0;k<j-1;k++)
{
if(l[k]>l[k+1]&&flag2==0) //在递增之前先递减。
{
flag1=1;
}
else if(l[k]<l[k+1]&&flag1==1) //递减之后递增 。
{
flag2=1;;
}
else flag=1; //出现其他情况侧则不是。
}
//printf("%d\n",flag);
if(flag==0&&flag1==1&&flag2==1)
ans++;
}
printf("%d",ans);
return 0;
}
由题意知,1~100之间没有U型数字,所以从101开始遍历,找到一个ans加 1。
D
题目
LIS是最长上升子序列。什么是最长上升子序列? 就是给你一个序列,请你在其中求出一段最长严格上升的部分,它不一定要连续。
就像这样:22, 33, 44, 77 和 22, 33, 44, 66 就是序列 22 55 33 44 11 77 66 的两个上升子序列,最长的长度是 44。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int N;
int arr[1005],dp[1005];
int mmp()
{
int ans=1;
for(int i=1;i<=N;i++)
{
dp[i]=1;
for(int j=1;j<i;j++)
{
if(arr[j]<arr[i]) //每进行一次循环,dp[i]都会变为当前最大的递增子序列。
dp[i]=max(dp[j]+1,dp[i]);
}
ans=max(ans,dp[i]); //找出N组递增子序列中最大的即可。
}
return ans;
}
int main()
{
scanf("%d",&N);
for(int i=1;i<=N;i++)
scanf("%d",&arr[i]);
int ans=mmp();
printf("%d\n",ans);
return 0;
}
这是原来的代码,用计蒜客上的AC代码好像有点子问题。
E
题目
相信大家都知道什么是全排列,但是今天的全排列比你想象中的难一点。我们要找的是全排列中,排列结果互不相同的个数。比如:aab 的全排列就只有三种,那就是aab,baa,aba。
代码框中的代码是一种实现,请分析并填写缺失的代码。
代码
#include <bits/stdc++.h>
using namespace std;
const int N=1e3;
char str[N], buf[N];//buffer
int vis[N], total, len;
void arrange(int num)
{
if (num == len)
{
printf("%s\n", buf);
total++;
return;
}
for (int i = 0; i < len; ++i)
{
if (!vis[i])
{
int j;
for (j = i + 1; j < len; ++j)
{
if (str[i]==str[j]&&vis[j]) //如果出现重复字符则break
{
break;
}
}
if (j == len)
{
vis[i] = 1;
buf[num] = str[i];
arrange(num + 1);
vis[i] = 0; //回溯。
}
}
}
}
int main()
{
while (~scanf("%s",str))
{
len = strlen(str);
sort(str, str + len);
total = 0;
buf[len] = '\0';
arrange(0);
printf("Total %d\n", total);
}
return 0;
}
F
题目
蒜头君今天突然开始还念童年了,想回忆回忆童年。他记得自己小时候,有一个很火的游戏叫做数独。便开始来了一局紧张而又刺激的高阶数独。蒜头君做完发现没有正解,不知道对不对? 不知道聪明的你能否给出一个标准答案?
标准数独是由一个给与了提示数字的 9×9 网格组成,我们只需将其空格填上数字,使得每一行,每一列以及每一个 3×3 宫都没有重复的数字出现。
输出这个数独得正解,输出格式如下:
* 2 6 * * * * * *
* * * 5 * 2 * * 4
* * * 1 * * * * 7
* 3 * * 2 * 1 8 *
* * * 3 * 9 * * *
* 5 4 * 1 * * 7 *
5 * * * * 1 * * *
6 * * 9 * 7 * * *
* * * * * * 7 5 *
把上面的 * 替换成 1 - 91−9 就可以了
提醒:两个数字之间要有一个空格,其他地方不要输出多余的符号。
代码
//这个题是百度出来的。
#include <bits/stdc++.h>
#define M 11
using namespace std;
struct point
{
int x, y;
} p[100];
bool flag, row[M][M], col[M][M], mat[3][3][M];
int np = 0;
int Map[M][M]= {
{0,2,6,0,0,0,0,0,0},
{0,0,0,5,0,2,0,0,4},
{0,0,0,1,0,0,0,0,7},
{0,3,0,0,2,0,1,8,0},
{0,0,0,3,0,9,0,0,0},
{0,5,4,0,1,0,0,7,0},
{5,0,0,0,0,1,0,0,0},
{6,0,0,9,0,7,0,0,0},
{0,0,0,0,0,0,7,5,0}};
void dfs(int n)
{
if(flag)
return;
if(n == -1) //当模拟的答案正确时输出。
{
for(int i=0;i<9 && !flag;i++)
{
for(int j=0;j<9;j++)
printf("%d ",Map[i][j]);
printf("\n");
}
flag = 1; //题目只要一种正确情况。
return;
}
for(int i=1;i<=9 && !flag;i++)
{
int x = p[n].x;
int y = p[n].y;
if(!row[x][i] && !col[y][i] && !mat[x/3][y/3][i])
{
row[x][i] = col[y][i] = mat[x/3][y/3][i] = true;
Map[x][y] = i;
dfs(n-1); //递归搜索
Map[x][y] = 0;
row[x][i] = col[y][i] = mat[x/3][y/3][i] = false; //回溯
}
}
}
int main()
{
flag = 0;
memset(row,false,sizeof(row)); //全部初始化。
memset(col,false,sizeof(col));
memset(mat,false,sizeof(mat));
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
int num = Map[i][j];
if(num)
{
row[i][num] = col[j][num] = mat[i/3][j/3][num] = true; //标记原来已有数据。
}
else
{
p[np].x = i;
p[np++].y = j;
}
}
}
dfs(np-1);
return 0;
}
G
题目
代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
double l[1005],arr[1005];
int n;
cin>>n;
cin>>arr[0]>>arr[n+2];
for(int i=1;i<=n;i++)
{
cin>>l[i];
}
arr[1]=0;
for(int i=2;i<=n+1;i++)
{
arr[i]=2*(arr[i-1]+l[i-1])-arr[i-2];
}
double ans=(arr[n+2]-arr[n+1])/(n+1);
printf("%.2lf",ans);
return 0;
}
H
题目
蒜头君被暗黑军团包围在一座岛上,所有通往近卫军团的路都有暗黑军团把手。幸运的是,小岛上有一扇上古之神打造的封印之门,可以通往近卫军团,传闻至今没有人能解除封印。
封印之门上有一串文字,只包含小写字母,有 k 种操作规则,每个规则可以把一个字符变换成另外一个字符。经过任意多次操作以后,最后如果能把封印之门上的文字变换成解开封印之门的文字,封印之门将会开启。
蒜头君战斗力超强,但是不擅计算,请你帮忙蒜头君计算至少需要操作多少次才能解开封印之门。
输入格式
输入第一行一个字符串,长度不大于 1000,只包含小写字母,表示封印之门上的文字。
输入第二行一个字符串,只包含小写字母,保证长度和第一个字符串相等,表示能解开封印之门的文字。
输入第三行一个整数 k(0≤k≤676)。
接下来 k 行,每行输出两个空格隔开的字符 a, bb,表示一次操作能把字符 a变换成字符 b。
输出格式
如果蒜头君能开启封印之门,输出最少的操作次数。否则输出一行 −1。
代码
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3fffffff
int main()
{
int l[30][30];
for(int i=0;i<26;i++)
{
for(int j=0;j<26;j++)
{
if(i==j)
{
l[i][j]=0;
}
else
{
l[i][j]=inf;
}
// cout<<l[i][j]<<" ";
}
//cout<<endl;
}
int n;
string s1,s2;
char a,b;
cin>>s1>>s2;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a>>b;
if(a!=b)
l[a-'a'][b-'a']=1;
}
for(int i=0;i<26;i++)
{
for(int j=0;j<26;j++)
{
for(int k=0;k<26;k++)
{
//cout<<l[j][k]<<endl;
l[j][k]=min(l[j][k],l[j][i]+l[i][k]);
//cout<<l[j][k]<<endl;
}
}
}
int sum=0;
for(int i=0;i<s1.size();i++)
{
if(l[s1[i]-'a'][s2[i]-'a']>=inf)
{
sum=-1;
break;
}
else
{
sum+=l[s1[i]-'a'][s2[i]-'a'];
// cout<<l[s1[i]-'a'][s2[i]-'a']<<endl;
}
}
cout<<sum;
return 0;
}
这个题类似于之前比赛时遇到的迪克斯特拉算法,详见博客凯迪克斯拉
I
题目
在一个星光摧残的夜晚,蒜头君一颗一颗的数这天上的星星。
蒜头君给在天上巧妙的画了一个直角坐标系,让所有的星星都分布在第一象。天上有 n 颗星星,他能知道每一颗星星的坐标和亮度。
现在,蒜头君问自己 q 次,每次他问自己每个矩形区域的星星的亮度和是多少(包含边界上的星星)。
输入格式
第一行输入一个整数 n(1≤n≤50000) 表示星星的数量。
接下里 nn 行,每行输入三个整数 x,y,w(0≤x,y,w≤2000),表示在坐标 (x,y) 有一颗亮度为 w 的星星。注意一个点可能有多个星星。
接下来一行输入一个整数 q(1≤q≤50000),表示查询的次数。
接下来 qq 行,每行输入四个整数 x1 ,y1,x2,y2,其中 (x1,y1) 表示查询的矩形的左下角的坐标,(x2,y2) 表示查询的矩形的右上角的坐标,0≤x1≤x2 ≤2000,0≤y1≤y2≤2000。
输出格式
对于每一次查询,输出一行一个整数,表示查询的矩形区域内的星星的亮度总和。
样例输入
5
5 0 6
7 9 7
8 6 13
9 7 1
3 0 19
4
0 8 7 9
0 0 7 10
2 7 10 9
5 4 7 5
样例输出
7
32
8
0
代码
用二维数组表示某位置之前的亮度总和,再用求前缀和的方法解决,类似于求大矩形中小矩形的面积。
#include<bits/stdc++.h>
using namespace std;
int l[2005][2005];
int main()
{
int n;
int x,y,w;
memset(l,0,sizeof(l));
cin>>n;
for(int i=0;i<n;i++)
{
cin>>x>>y>>w;
l[x+1][y+1]+=w;
}
for(int i=1;i<2005;i++)
{
for(int j=1;j<2005;j++)
{
l[i][j]+=l[i-1][j]+l[i][j-1]-l[i-1][j-1];
}
}
int q,x1,x2,y1,y2;
cin>>q;
int sum=0;
for(int i=0;i<q;i++)
{
sum=0;
cin>>x1>>y1>>x2>>y2;
sum=l[x2+1][y2+1]+l[x1][y1]-l[x2+1][y1]-l[x1][y2+1];
cout<<sum<<endl;
}
return 0;
}
J
看不懂T^T