1. 程式人生 > 實用技巧 >【訓練賽】ICPC Central Russia Regional Contest (CRRC 18)

【訓練賽】ICPC Central Russia Regional Contest (CRRC 18)

C Dimensions

題目傳送門:

https://codeforces.com/gym/102785/problem/C

題意:

給一串字元,有‘*’‘/’‘()’,輸出約分後的分子和分母。按照給定的字典序輸出

思路

用棧讀入,存放,約分。map儲存。唯一要注意的是,約完是輸出1.

程式碼

#include <bits/stdc++.h>
using namespace std;
const int kMaxN = 1005;
string s;
inline bool cmp(char a, char b) {
    if (tolower(a) != tolower(b))
        return tolower(a) < tolower(b);
    return a < b;
}
struct String {
    string s;
    String(const string &_s) {
        s = _s;
    }
    inline bool operator<(const String &other) const {
        for (int i = 0; i < min((int)s.length(), (int)other.s.length()); ++i) {
            if (s[i] == other.s[i])
                continue;
            return cmp(s[i], other.s[i]); 
        }
        return s.length() < other.s.length();
    }
};

map<String, int> mp[2];
void resolve(int l, int r, int d) {
    for (int i = l, c = d; i <= r; ) {
        
        if (s[i] == '*') {
            c = d;
            ++i;
        } else if (s[i] == '/') {
            c = d ^ 1;
            ++i;
        } else if (s[i] == '(') {
            int p = 1, j;
            for (j = i + 1; j <= r; ++j) {
                if (s[j] == '(')
                    ++p;
                if (s[j] == ')')
                    --p;
                if (p == 0)
                    break;
            }
            resolve(i + 1, j - 1, c);
            i = j + 1;
        } else {
            int j;
            for (j = i; j <= r; ++j) {
                if (!isalpha(s[j]))
                    break;
            }
            ++mp[c][s.substr(i, j - i)];
            i = j;
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin >> s;
    resolve(0, s.length() - 1, 0);
    for (auto it : mp[0]) {
        if (mp[1][it.first] > 0) {
            int c = min(mp[1][it.first], mp[0][it.first]);
            mp[1][it.first] -= c;
            mp[0][it.first] -= c;
        }
    }
    bool first = true;
    for (auto it : mp[0]) {
        while (it.second--) {
            if (!first)
                cout << "*" << it.first.s;
            else {
                cout << it.first.s;
                first = false;
            }
        }
    }
    if (first)
        cout << 1;
    cout << endl;
    first = true;
    for (auto it : mp[1]) {
        while (it.second--) {
            if (!first)
                cout << "*" << it.first.s;
            else {
                cout << it.first.s;
                first = false;
            }
        }
    }
    if (first)
        cout << 1;
    cout << endl;
    return 0;
}

D We were trying to share an orange

題目傳送門:

https://codeforces.com/gym/102785/problem/D

題意:

給一個數k,輸出最小的因子個數為k個的數

思路:

找規律發現若k是質數,則答案是2^(k-1),其他結果可以進行搜尋。因為k<1000,因此要用高精度.

程式碼實現:

#include <bits/stdc++.h>
using namespace std;
int a[20]={2,3,5,7,11,13,17,19,23,29};
string ans="1";
string mul(string a, int b)
{
    const int L = 505;
    int na[L];
    string ans;
    int La = (int)a.size();
    fill(na, na + L, 0);
    for (int i = La - 1; i >= 0; i--) na[La - i - 1] = a[i] - '0';
    int w = 0;
    for (int i = 0; i < La; i++){
        na[i] = na[i] * b + w;
        w = na[i] / 10;
        na[i] = na[i] % 10;
    }
    while (w) {
        na[La++] = w % 10;
        w /= 10;
    }
    La--;
    while (La >= 0) ans += na[La--] + '0';
    return ans;
}

bool cmp(string x,string y){
    if(x.length()==y.length()){
        return x<y;
    }
    else return x.length()<y.length();
}

void dfs(string s,int k,int up,int ii){
    if(k==1){
        if(cmp(s,ans))ans=s;
    }
    for(int i=2;i<=min(k,up);i++){
        if(k%i==0){
            string ss=s;
            for(int j=1;j<i;j++){
                ss=mul(ss,a[ii]);
                if(cmp(ans,ss))return;
            }
            dfs(ss,k/i,i,ii+1);
        }
    }
}
int main(){
    int n;
    scanf("%d",&n);
    for(int i=0;i<450;i++)ans+='0';
    dfs("1",n,n,0);
    cout<<ans<<endl;
    return 0;
}

H、A self-describing sequence

題目傳送門:

https://codeforces.com/gym/102785/problem/H

題意:

給定一個k,構造一個序列,滿足原序列是0-(k-1),且構造序列對應原序列是原序列的數在構造序列的個數。如:

0 1 2 3

1 2 1 0

0在構造序列的個數是1,1在構造序列的個數為2,2在構造序列的個數為1,3在構造序列的個數為0

如果沒有這個序列,則輸出0;
給定一個n,輸入n個數,輸出這n個數對應的構造序列的數字。

思路:

我們找規律可以發現,當k=1,2,3,6的時候,答案無解。

當k=4和5的時候需要特殊構造(手動構造就好)

當k>=7時,a[0]=k-4 a[1]=2 a[2]=1 a[k-1]=1 其他為0.

程式碼實現:

#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
using namespace std;
const int N=1e5+3; 
ll k,n,a[N];
int main(){
	scanf("%lld%lld",&k,&n);
	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
	if(k==1 || k==2 || k==3 ||k==6)
		printf("0\n");
	else if(k==4) {
		printf("%lld\n",n);
		for(int i=1;i<=n;i++) {
			if(a[i] == 0) printf("1 ");
			else if(a[i] == 1) printf("2 ");
			else if(a[i] == 2) printf("1 ");
			else if(a[i] == 3) printf("0 ");
		}
	}
	else if(k==5) {
		printf("%lld\n",n);
		for(int i=1;i<=n;i++) {
			if(a[i]==0) printf("2 ");
			else if(a[i]==1) printf("1 ");
			else if(a[i]==2) printf("2 ");
			else printf("0 ");
		}
	}
	else {
		printf("%lld\n",n);
		for(int i=1;i<=n;i++) {
			if(a[i]==0) printf("%lld ",k-4);
			else if(a[i]==1) printf("2 ");
			else if(a[i]==2) printf("1 ");
			else if(a[i]==k-4) printf("1 ");
			else printf("0 ");
		}
	}
	return 0;
}

對於構造題,如果半個小時都沒有思路,在賽場上應該選擇放棄。構不出來就是構不出來。如果想解除構造題,應該不只是想,更需要藉助其他程式碼進行打表或者搜尋,來尋找規律(大佬一眼看出。