XP的组合数
时间限制: 1 内存限制: 128 MB
题目描述
XP喜欢组合数。现在有这样一个问题,给定1-n的数字,要求这些数字组成的所有可能的数的和,例如n=3时,有6种组合123+132+213+312+321=1332。现在给定n要求你求出这n个数字组成的可能的数的总和。
输入
第一行输入一个n(n<=10)。
输出
输出上述要求的总和。
样例输入
3
样例输出
1332
简单搜索
AC Code:
#include <cstdio>
#include <cmath>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<map>
#include<queue>
#include<climits>
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
using namespace std;
typedef long long ll;
static const int MAX_N = 2e5 + 5;
int n;
ll res;
bool vis[15];
void dfs(ll s, int len){
if(len == n){
res += s;
return;
}
if(len > n) return;
for(int i = 1; i <= n; i++){
if(vis[i]) continue;
vis[i] = true;
dfs(s * 10 + i, len + 1);
vis[i] = false;
}
}
int main(){
while(scanf("%d", &n) != EOF){
memset(vis, false, sizeof(vis));
res = 0;
for(int i = 1; i <= n; i++){
vis[i] = true;
dfs(i, 1);
vis[i] = false;
}
printf("%lld\n", res);
}
return 0;
}
XP的座次表
时间限制: 1 内存限制: 128 MB
题目描述
XP迎来了他大学第一堂期末考试,老师开始安排考场座次,第一列从第一个同学开始从前往后按照学号(学号从1开始递增)升序排列,然后第二列接着第一列最后一个同学的学号从后往前按照学号升序排列,第三列又从第一个同学开始接着第二列的第一个同学的学号从前往后按照学号升序排列,......,依次类推。为了简化问题,我们假设考场有n行n列,你能够帮XP编写一个程序生成考场座次表吗?
输入
单组输入数据
n(n<=20)
输出
一个n行n列的座次表,注意每列的学号要向右对齐,且行末不要有多余的空格
样例输入
4
样例输出
1 8 9 16
2 7 10 15
3 6 11 14
4 5 12 13
座位表很容易打印出来,主要是要控制每列应该右对齐的格式(记录占几个字节)
AC Code:
#include <iostream>
#include<cstdint>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<climits>
using namespace std;
static const int MAX_N = 1e6 + 5;
typedef long long ll;
int vmax[25];
int vv[25][25];
int main(){
int n, y;
scanf("%d", &n);
vv[1][1] = 1;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
if(i == 1 && j == 1) continue;
if(j % 2 == 0){
if(i == 1) vv[i][j] = vv[i][j - 1] + 2 * n - 1;
else vv[i][j] = vv[i - 1][j] - 1;
}
else {
if(i == 1) vv[i][j] = vv[i][j - 1] + 1;
else vv[i][j] = vv[i - 1][j] + 1;
}
}
}
for(int j = 1; j <= n; j++){
int t = max(vv[1][j], vv[n][j]);
int res = 0;
while(t){
t /= 10;
res++;
}
vmax[j] = res;
}
for(int i = 1; i <= n; i++){
if(vmax[1] == 1) printf("%d ", vv[i][1]);
else if(vmax[1] == 2) printf("%2d ", vv[i][1]);
for(int j = 2; j < n; j++){
if(vmax[j] == 1) printf("%d ", vv[i][j]);
else if(vmax[j] == 2) printf("%2d ", vv[i][j]);
else if(vmax[j] == 3) printf("%3d ", vv[i][j]);
}
if(vmax[n] == 1) printf("%d\n", vv[i][n]);
else if(vmax[n] == 2) printf("%2d\n", vv[i][n]);
else if(vmax[n] == 3) printf("%3d\n", vv[i][n]);
}
return 0;
}
1393: XP的翻转
时间限制: 1 内存限制: 128 MB
提交: 14 解决: 4
题目描述
给定两组长度相等的字符串由‘0‘和’1‘组成,分别为初始态和目标态。
每次可以选择任意的区间翻转(区间内的‘0’->'1','1'->'0')。
问从初始态到目标态最少需要多少次。
输入
多组数据。
每组数据为两行字符串,分别表示初始态s和目标态t。(0<|s|=|t|<=100000)
输出
对于每组数据,输出一个整数表示答案
样例输入
01
01
01
10
样例输出
0
1
求两个字符串有多少个不同的区间
AC Code:
#include <iostream>
#include<cstdint>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<climits>
using namespace std;
static const int MAX_N = 1e6 + 5;
typedef long long ll;
int main(){
char s1[100005], s2[100005];
while(scanf("%s%s", s1, s2) != EOF){
int len = strlen(s1);
int i = 0, res = 0;
while(i < len){
if(s1[i] == s2[i]) {
i++;
}
else {
res++;
i++;
while(s1[i] != s2[i] && i < len){
i++;
}
}
}
printf("%d\n", res);
}
return 0;
}
1383: XP的演讲比赛
时间限制: 1 内存限制: 128 MB
提交: 13 解决: 5
题目描述
XP参加了学校的演讲比赛,比赛共分为两轮,每一轮比赛得分各占总得分的50%。在最终结果公布之前,XP只知道在两轮的排名情况,但不知道具体分数,最终结果将按照两轮总得分升序排列。聪明的你能够告诉XP,他最喜欢的G在最终排名中可能得到的最好名次和最差名次吗?
输入
第一行输入n,表示参赛选手的人数(n<=26)
第二行输入n个字符,表示第一轮的排名情况
第三行输入n个字符,表示第二轮的排名情况
输出
输出一行 两个数分别为G的最好名次和最差名次,用空格隔开
样例输入
10
A B C D E F G H I J
A C I G E F J H D B
样例输出
3 8
最好成绩就是只有两次成绩都在G前面的同学成绩比G高,最坏成绩就是只有两次成绩都在G后面的同学成绩比G低
AC Code:
#include <iostream>
#include<cstdint>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<climits>
using namespace std;
static const int MAX_N = 1e6 + 5;
typedef long long ll;
char s1[26], s2[26];
int main(){
int n, pos1, pos2;
scanf("%d", &n);
getchar();
for(int i = 0; i < n; i++){
scanf("%c", &s1[i]);
getchar();
if(s1[i] == 'G') pos1 = i;
}
for(int i = 0; i < n; i++){
scanf("%c", &s2[i]);
getchar();
if(s2[i] == 'G') pos2 = i;
}
int res1 = 1;
for(int i = 0; i < pos1; i++){
for(int j = 0; j < pos2; j++){
if(s1[i] == s2[j]) {
res1++;
break;
}
}
}
int res2 = 0;
for(int i = pos1 + 1; i < n; i++){
for(int j = pos2 + 1; j < n; j++){
if(s1[i] == s2[j]) {
res2++;
break;
}
}
}
printf("%d %d\n", res1, n - res2);
return 0;
}
1382: XP的全排列
时间限制: 1 内存限制: 128 MB
提交: 27 解决: 6
题目描述
xp想用1-9九个数字组成数学公式:
其中ABCDEFGHI每一个字符均对应一个不同的数字,你能帮xp输出所有的组合吗?
输入
输出格式为
ABCD/EFGHI
每个结果占一行
输出
输出结果按分子大小降序
提前枚举四位数的不同位数情况,满足情况的五位数最大只能为29618(9876 * 3 = 29628)
再用函数判断4位数和5位数是否含有重复数字
这题数据有点水,就两个输出。。。感觉运气好猜都猜的对
Code:
/*
5832/17496
5823/17469
*/
#include <iostream>
#include<cstdint>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<climits>
#include<map>
using namespace std;
static const int MAX_N = 1e6 + 5;
typedef long long ll;
bool vis[9999];
void init(){
for(int i = 1000; i <= 9999; i++) vis[i] = false;
for(int i = 1; i <= 9; i++){
for(int j = 1; j <= 9; j++){
if(i == j) continue;
for(int k = 1; k <= 9; k++){
if(i == j || i == k || j == k) continue;
for(int t = 1; t <= 9; t++){
if(i == j || i == k || i == t || j == k || j == t || k == t) continue;
vis[i * 1000 + j * 100 + k * 10 + t] = true;
}
}
}
}
}
bool is_right(int x, int y){
map<int, bool>mps;
while(x){
if(mps[x % 10] || x % 10 == 0) return false;
mps[x % 10] = true;
x /= 10;
}
while(y){
if(mps[y % 10] || y % 10 == 0) return false;
y /= 10;
}
return true;
}
int main(){
init();
for(int i = 29628; i >= 12345; i--){
double v = i / 3.0;
if(v > 9876) continue;
if(v == (int)v ){
if(vis[(int)v] && is_right(i, (int)v))
printf("%d/%d\n", (int)v, i);
}
}
}