1. 程式人生 > >UP !

UP !

                                           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);
        }
   }
}