1. 程式人生 > >FJNU2018低程F jq解救fuls (貪心亂搞)題解

FJNU2018低程F jq解救fuls (貪心亂搞)題解

題目描述

一天fuls被邪惡的"咕咕咕"抓走了,jq為了救fuls可謂是赴湯蹈火,費了九牛二虎之力才找到了"咕咕咕"關押fuls的地方。 
fuls被關在一個機關中,想要解救fuls必須解答出機關的問題,在機關上會顯示兩個整數N和M,jq必須在機關上輸入N個只包含'A'和'C'的字元形成串str, 
在這個串中存在f(i,j),i<j,表示str[i]=='C'和str[j]=='A'的一個反AC對,此字串必須包含剛好M個反AC對,如果有多個長度為N的串滿足條件,那麼字典序最大的那個才是正確的。 
字典序大小: 
        若字串a>字串b即存在位置i使得0<=j<i,a[j]==b[j],a[i]>b[i]。 

 

輸入

第一行輸入一個t表示樣例個數。(1<=t<=100) 
接下來t行每行包含兩個整數N和M(1<=N<=60,0<=M<=N*(N-1)/2) 

 

輸出

每個樣例輸出一行字串表示jq的答案,若某次詢問無解則輸出"jq lost fuls!"(輸出無雙引號)。 

 

樣例輸入

2
5 4
3 3

 

樣例輸出

CCCCA
jq lost fuls!

附送幾組資料:

10 23
CCCCCACAAA
10 22
CCCCCAACAA
10 0
CCCCCCCCCC

 

思路:在隊友AC的瞬間想到了思路...

問題可以理解為就是給你長度n,求字典序最大的、CA對數為m的答案。顯然長度為n的串CA對數最大為Max = (n / 2) * (n - n / 2)。那麼超過這個值就不存在答案。

顯然A越少整個串就可能字典序越大,那麼我們從A為0開始找,找到這種情況下形成最多的CA對數(即(n-a)*a),如果當前A的個數形成的CA對數已經>=m了,那麼顯然A最多就這麼多了。

假設此時A個數為a,C的個數為c=n-a,此時已經滿足c*a>=m。我們可以知道,如果交換CA,那麼CA對數會減少1,那麼我們只要不斷逼近m,最後一直減一就能減到m了。所以我們不斷減小c,但是繼續滿足c*a>=m,那麼終有一天,會變成c*a>=m並且(c-1)*a<m,這時候已經逼近成功了,只需要移動最後一個C就行了。然後在最後還沒填完的地方加C。

為了防止有萌新誤入此地看不懂題解,我決定模擬一下過程:

10 23

a = 0,最大0個CA對,pass

a = 1,最大9個CA對,pass

a = 2,最大16個CA對,pass

a = 3,最大21個CA對,pass

a = 4,最大24個CA對,開始逼近

c = 6,a = 4,顯然c不可能再小了,此時的串為CCCCCCAAAA,值為24

移動最後一個C,變成CCCCCACAAA,值為23,末尾也不用填C,真相只有一個答案是CCCCCACAAA

程式碼:

#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
typedef long long ll;
using namespace std;
const int maxn = 1000 + 10;
const int seed = 131;
const ll MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
char ans[70];
int main(){
    int t;
    scanf("%d", &t);
    for(int p = 0; p < t; p++){
        int n , m;
        scanf("%d%d", &n, &m);
        int Max = (n / 2) * (n - n / 2);
        if(m > Max){
            printf("jq lost fuls!\n");
        }
        else{
            int len = n;
            int C, A;
            for(int i = 0; i <= m; i++){
                int c = len - i, a = i;
                if(c + a <= len && c * a >= m){
                    while((c - 1) * a >= m && a != 0) c--;
                    C = c;
                    A = a;
                    break;
                }
            }
            for(int i = 1; i <= C + A; i++){
                if(i <= C){
                    ans[i] = 'C';
                }
                else{
                    ans[i] = 'A';
                }
            }
            int M = C * A;
            int now = C;
            while(m < M){
                swap(ans[now], ans[now + 1]);
                now++;
                M--;
            }
            for(int i = 1; i <= C + A; i++)
                printf("%c", ans[i]);
            for(int i = 1; i <= n - C - A; i++)
                printf("C");
            printf("\n");
        }
    }
    return 0;
}