CodeTON Round 9 (Div. 1 + Div. 2, Rated, Prizes!)(A~C2)

Ke_scholar發表於2024-11-28

A - Shohag Loves Mod

思路

假設構造差值是 \(x = 0,1,\dots ,n\) 這樣的,那麼只要讓 \(a_i \equiv x \pmod{i}\) 即可,也就是 \(a_i = i+x\)

程式碼

#include <bits/stdc++.h>

using namespace std;

using i64 = long long;

void solve() {

    int n;
    cin >> n;

    for (int i = 1; i <= n; i ++) {
        cout << i + i - 1 << " \n"[i == n];
    }

}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int t;
    cin >> t;
    while (t--) {
        solve();
    }

    return 0;
}

B. Shohag Loves Strings

思路

其實只要找到形如 aaabc這種兩個一樣或三個不一樣的就可以,但是很不懂啊,我最開始寫得就是用 substr 去擷取的,但是一直 \(WA\),後來索性就直接暴力搞了。

程式碼

#include <bits/stdc++.h>

using namespace std;

using i64 = long long;

void solve() {

    string s;
    cin >> s;

    int n = s.size();
    for (int len : {2, 3, 4, 5}) {
        for (int i = 0; i + len <= n; i ++) {
            set<string> t;
            for (int l = i; l < i + len; l ++) {
                for (int r = l; r < i + len; r ++) {
                    t.insert(s.substr(l, r - l + 1));
                }
            }
            if (t.size() % 2 == 0) {
                cout << s.substr(i, len) << "\n";
                return;
            }
        }
    }
    cout << "-1\n";

}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int t;
    cin >> t;
    while (t--) {
        solve();
    }

    return 0;
}

C1 - Shohag Loves XOR (Easy Version)

思路

題目給定範圍 \(\sum n \le 1\times 10^7\),那麼直接列舉找 \(y\) 即可。

程式碼

#include <bits/stdc++.h>

using namespace std;

using i64 = long long;

void solve() {

    int x;
    i64 m;
    cin >> x >> m;

    int ans = 0;
    for (int i = 1; i < x; i ++) {
        if ((x % i == 0 || (i ^ x) % i == 0 ) && x != (i ^ x) && (i ^ x) <= m) {
            ans ++;
        }
    }

    cout << ans << "\n";

}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int t;
    cin >> t;
    while (t--) {
        solve();
    }

    return 0;
}

C2 - Shohag Loves XOR (Hard Version)

思路

唉唉,數學分類討論題,感覺這題就應該和 \(D\) 題換個位置,賽時分析了一半看了一眼榜就去寫 \(D\) 了,QWQ。

以下要用到的關於異或的性質,不作證明。
\(1、x-y\le x\oplus y \le x + y\)
\(2、x\oplus x = 0\)
\(3、x\oplus y = z \Rightarrow x = z \oplus y\)

\(p = x\oplus y\),考慮三種情況,\(p\)\(x\) 整除,\(p\)\(y\) 整除,\(p\)\(\text{lcm}(x,y)\) 整除。

  • \(p\)\(x\) 整除的時候:
    那麼 \(y = p\oplus x,p = k\times x:\)

    \[\because 1\le y\le m\\\\ \therefore p\oplus x\le m\\\\ 且當 p\oplus x \le p + x \le m 時,p\le m-x\\\\ 那麼 x 的倍數有 \left\lfloor\frac{m-x}{x}\right\rfloor 個.\\\\ 這裡有兩個 x 的倍數需要特殊討論:\\\\ 一個是0,即當x\le m的時候,0是可取的;\\\\ 當x\le m-x的時候,會取到x為本身的倍數,但是x\oplus x=0<1,所以我們需要去掉.\\\\ 當 p\oplus x \ge p - x > m 時,p > m + x\\\\ 但是 y \le m,\therefore p\not\in(m+x,+\infty)\\\\ \therefore (m-x,m+x] 的範圍內最多有兩個 x 的倍數,直接列舉即可.\]

  • \(p\)\(y\) 整除的時候:
    • \(x<y:\)

    \[\because x > 0\And y>0\\\\ \therefore p=x\oplus y \ne x \And p \ne y\\\\ \therefore 當y>x時,p至少為y的2倍\\\\ 但是 p\le x + y < 2\max(x,y)=2y\\\\ \therefore 此時不存在p.\]

    • \(x\ge y\)

      \[此時x\le 1\times 10^6,直接列舉即可. \]

  • \(p\)\(\text{lcm}(x,y)\) 整除的時候:
    • \(x\ne y:\)

      \[此時\text{lcm}(x,y)\ge 2\max(x,y)\\\\ 但是由上述推導可知p < 2\max(x,y)\\\\ \therefore 此時不存在 p.\]

    • \(x=y:\)

    \[當x\le m 時,存在一個p. \]

程式碼

#include <bits/stdc++.h>

using namespace std;

using i64 = long long;

void solve() {

	int x;
	i64 m;
	cin >> x >> m;

	i64 ans = max(m - x, 0LL) / x + (x <= m);
	ans -= (x <= m - x);
	for (i64 i = max(m - x, 0LL) + 1; i <= m + x; i++) {
		if (i % x == 0 && (i ^ x) <= m && (i ^ x) > 0) {
			ans ++;
		}
	}
	
	for (int i = 1; i <= min<i64>(x, m); i ++) {
		if ((i ^ x) % i == 0) {
			ans ++;
		}
	}

	cout << ans - (x <= m) << "\n";

}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int t;
	cin >> t;
	while (t--) {
		solve();
	}

	return 0;
}

D - Shohag Loves GCD

思路

這題也是唐完了。

要使得 \(a_{\gcd(i,j)} \ne \gcd(a_i,a_j)\),且還要讓 \(a\) 陣列儘可能大,假設 \(a_i\) 是較大的數,那麼只要讓 \(i\) 的倍數取較小的值即可,但是這裡可能會存在問題就是,比如 \(2\) 的倍數 \(4\)\(8\) 又不能填一樣的,這裡其實就用到了尤拉篩的思想,每個合數都只會被它最小質因數的另一個因子篩掉,這樣就可以保證當後面的數對存在 \(\gcd \ne\) 當前 \(i\) 的時候及時退出了,時間複雜度是 \(\mathcal{O}(n)\)

當然這個題還有另外一種思路,就是對於每一個 \(i\) 來說,都去直接列舉 \(i\) 的倍數,然後後面的數的倍數又會把前面的某些數的倍數給覆蓋掉,也能保證每個數的倍數的 \(a_i\)\(\gcd\) 不會與前面重合,時間複雜度是調和級數級別,也就是 \(\mathcal{O}(n\ln n)\)

不過在 \(cf\) 上貌似兩種寫法也沒有太大的時間差距,跑得都很快就是了。

程式碼(尤拉篩寫法)

#include <bits/stdc++.h>

using namespace std;

using i64 = long long;

void solve() {

    int n, m;
    cin >> n >> m ;

    set<int> s;

    vector<int> a(m + 1);
    for (int i = 1; i <= m; i ++) {
        cin >> a[i];
    }

    sort(a.begin() + 1, a.end(), greater<>());

    vector<array<int, 2>> ans(n + 1, {0, 0});
    ans[1] = {a[1], 1};
    vector<int> pr;
    for (int i = 2; i <= n; i ++) {
        if (!ans[i][0]) {
            if (m < 2) {
                cout << "-1\n";
                return ;
            }
            pr.emplace_back(i);
            ans[i] = {a[2], 2};
        }
        for (int j = 0; j < pr.size() && pr[j] <= n / i; j ++) {
            if (m < ans[i][1] + 1) {
                cout << "-1\n";
                return;
            }
            ans[i * pr[j]] = {a[ans[i][1] + 1], ans[i][1] + 1};
            if (i % pr[j] == 0) break;
        }
    }

    for (int i = 1; i <= n; i ++) {
        cout << ans[i][0] << " \n"[i == n];
    }

}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int t = 1;
    cin >> t;
    while (t--) {
        solve();
    }

    return 0;
}

程式碼(列舉倍數)

#include <bits/stdc++.h>

using namespace std;

using i64 = long long;

void solve() {

    int n, m;
    cin >> n >> m ;

    set<int> s;

    vector<int> a(m + 1);
    for (int i = 1; i <= m; i ++) {
        cin >> a[i];
    }

    sort(a.begin() + 1, a.end(), greater<>());

    vector<array<int, 2>> ans(n + 1, {0, 0});
    ans[1] = {a[1], 1};
    vector<int> pr;
    for (int i = 2; i <= n; i ++) {
        if (!ans[i][0]) {
            if (m < 2) {
                cout << "-1\n";
                return ;
            }
            pr.emplace_back(i);
            ans[i] = {a[2], 2};
        }
        for (int j = i + i; j <= n; j += i) {
            if (m < ans[i][1] + 1) {
                cout << "-1\n";
                return;
            }
            ans[j] = {a[ans[i][1] + 1], ans[i][1] + 1};
        }
    }

    for (int i = 1; i <= n; i ++) {
        cout << ans[i][0] << " \n"[i == n];
    }
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int t = 1;
    cin >> t;
    while (t--) {
        solve();
    }

    return 0;
}

相關文章