CodeTON Round 9 (Div. 1 + Div. 2, Rated, Prizes!)
4/11(A B C1 D)
A. Shohag Loves Mod
題目大意
Shohag有一個整數nn。請幫助他找到一個遞增的整數序列1≤ a1<a2<…<an≤1001≤a1<a2<…<an≤100,使得對於所有的 1≤i<j≤n1≤i<j≤n,都滿足aimodi≠ajmodjaimodi≠ajmodj ∗∗。在給定的約束條件下,可以證明這樣的序列總是存在的。∗∗amodbamodb 表示aa除以bb的餘數。例如,7 mod 3=1,8 mod 4=0 7mod 3 = 1,8 mod 4 = 0,69 mod 10 = 9 69 mod 10 = 9。
要讓每個位置的值模上位置數都是第一次出現也就是\(a_i\) \(mod\) \(i\) 的結果是第一次出現比較好的就是讓第一個位置這樣的結果是0 後面是1然後依次類推0 1 2 3 4 5 6 .......,這樣就能保證每個位置的結果不一樣了,我們只需要讓a[i] = i + i就好了
// Problem: A. Shohag Loves Mod
// Contest: Codeforces - CodeTON Round 9 (Div. 1 + Div. 2, Rated, Prizes!)
// URL: https://codeforces.com/contest/2039/problem/0
// Memory Limit: 256 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
//by codeforcer ——
// ____ _ _ _ _ _ _ ____ _
// / ___|| | | || | | || | | | |___ \ | |
//| | | |_| || |_| || |_| | __) | | |
//| | | _ || _ || _ | |__ < | |
//| |___ | | | || | | || | | | ___) | | |
// \____||_| |_||_| |_||_| |_| |____ / |_|
#include<bits/stdc++.h>
using namespace std;
typedef int E;
typedef long long LL;
typedef pair<int, int> PII;
typedef tuple<int, int, int> PIII;
typedef tuple<LL, LL, LL> PLLL;
typedef pair<long long, long long> PLL;
typedef unsigned long long ULL;
#define endl '\n'
#define vec vector
#define pb push_back
#define pob pop_back
#define fir first
#define sec second
#define maxINT 0x3f3f3f3f
#define maxLL 0x3f3f3f3f3f3f3f3fLL
#define umap unordered_map
#define uset unordered_set
#define maxheap priority_queue<E, vector<E>, less<E>>
#define minheap priority_queue<E, vector<E>, greater<E>>
#define prvec(a) \
for (int i = 0; i < (a).size(); i++) { \
cout << (a)[i] << " "; \
} \
cout << endl;
#define debug0(a) \
cout << #a << ": "; \
for (int k = 0; k < (a).size(); k++) { \
cout << (a)[k] << " "; \
} \
cout << endl;
#define debug1(a) \
cout << #a << ": "; \
for (int k = 1; k <= (a).size(); k++) { \
cout << (a)[k] << " "; \
} \
cout << endl;
LL gcd(LL a, LL b) { return (b) ? gcd(b, a % b) : a; }
LL exgcd(LL a, LL b, LL &x, LL &y) {if (b == 0) { x = 1, y = 0; return a; }LL gcd = exgcd(b, a % b, y, x);y -= a / b * x;return gcd;}
LL qmi(LL a, LL b, LL mod) {LL res = 1;while (b) {if (b & 1) res = res * a % mod;a = a * a % mod;b >>= 1;}return res;}
const int N = 200010;
void solve() {
int n;
cin>>n;
for(int i = 1;i <= n;i ++)
{
cout<<i + (i - 1)<<" ";
}
cout<<endl;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n;cin>>n;while(n --)
solve();
return 0;
}
B. Shohag Loves Strings
題目大意:
對於一個字串p,令f(p)表示p的獨特非空子串的數量。
Shohag有一個字串s。幫助他找到一個非空字串p,使得p是s的子串且f(p)為偶數,或者說明不存在這樣的字串。
∗如果一個字串a可以透過從字串b中刪除開頭和/或結尾的若干個(可能是零個或全部)字元而得到,則字串a是字串b的子串。
考慮最小滿足獨立子串為偶數這一性質的子串p,可以發現最小就兩種情況:兩個連續相同字元,三個連續不相同字元,例如:aa ,abc的獨立子串個數就是偶數個aa 只有 aa a這兩個獨立子串,遍歷字串就行了
// Problem: B. Shohag Loves Strings
// Contest: Codeforces - CodeTON Round 9 (Div. 1 + Div. 2, Rated, Prizes!)
// URL: https://codeforces.com/contest/2039/problem/B
// Memory Limit: 256 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
//by codeforcer ——
// ____ _ _ _ _ _ _ ____ _
// / ___|| | | || | | || | | | |___ \ | |
//| | | |_| || |_| || |_| | __) | | |
//| | | _ || _ || _ | |__ < | |
//| |___ | | | || | | || | | | ___) | | |
// \____||_| |_||_| |_||_| |_| |____ / |_|
#include<bits/stdc++.h>
using namespace std;
typedef int E;
typedef long long LL;
typedef pair<int, int> PII;
typedef tuple<int, int, int> PIII;
typedef tuple<LL, LL, LL> PLLL;
typedef pair<long long, long long> PLL;
typedef unsigned long long ULL;
#define endl '\n'
#define vec vector
#define pb push_back
#define pob pop_back
#define fir first
#define sec second
#define maxINT 0x3f3f3f3f
#define maxLL 0x3f3f3f3f3f3f3f3fLL
#define umap unordered_map
#define uset unordered_set
#define maxheap priority_queue<E, vector<E>, less<E>>
#define minheap priority_queue<E, vector<E>, greater<E>>
#define prvec(a) \
for (int i = 0; i < (a).size(); i++) { \
cout << (a)[i] << " "; \
} \
cout << endl;
#define debug0(a) \
cout << #a << ": "; \
for (int k = 0; k < (a).size(); k++) { \
cout << (a)[k] << " "; \
} \
cout << endl;
#define debug1(a) \
cout << #a << ": "; \
for (int k = 1; k <= (a).size(); k++) { \
cout << (a)[k] << " "; \
} \
cout << endl;
LL gcd(LL a, LL b) { return (b) ? gcd(b, a % b) : a; }
LL exgcd(LL a, LL b, LL &x, LL &y) {if (b == 0) { x = 1, y = 0; return a; }LL gcd = exgcd(b, a % b, y, x);y -= a / b * x;return gcd;}
LL qmi(LL a, LL b, LL mod) {LL res = 1;while (b) {if (b & 1) res = res * a % mod;a = a * a % mod;b >>= 1;}return res;}
const int N = 200010;
void solve() {
string s;
cin>>s;
if(s.size() == 1) {cout<<-1<<endl;return;}
for(int i = 0;i + 2< s.size();i ++)
{
char a1 = s[i],a2 = s[i + 1],a3 = s[i + 2];
if(a1 != a2 && a1 != a3 && a3 != a2)
{
cout<<a1<<a2<<a3<<endl;
return;
}
if(a1 == a2)
{
cout<<a1<<a2<<endl;
return;
}else if(a2 == a3)
{
cout<<a2<<a3<<endl;
return;
}
}
if(s.size() == 2&&s[0] == s[1])
{
cout<<s<<endl;
return;
}
cout<<-1<<endl;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n;cin>>n;while(n --)
solve();
return 0;
}
C1. Shohag Loves XOR (Easy Version)
題目大意
Shohag有兩個整數x和m。幫助他計算1≤y≤m範圍內的整數數量,使得x≠y且x⊕y是x、y或者兩者的約數。這裡⊕是按位異或運算子。∗如果存在整數c使得a=b⋅c,則數b是數a的約數。
首先我們要知道如果x ⊕ y 是x的約數,就必須是x ⊕ y 小於 x ,是y的約數也是同理。
但是我們會驚奇的發現,如果y比x大很多,比如x = 6,y = 27 在二進位制上表示就是x = \((110)_2\) y = \((11011)_2\)
x ⊕ y 的結果的最高位一定是和y的最高位是一樣的,y的最高位一直是異或上0,1 ⊕ 0 結果是1,這就得提到另一個性質了,
如果一個數a的二進位制表示和b的二進位制表示的最高位位數是一樣的比如a = \((11011)_2\) 和 b = \((11000)_2\) 的最高位都是 \(2^4\) ,
那麼b一定不是a的約數,因為b是a的約數的情況是a最大是a/2 也就是a>>1在二進位制上最高位是低於a的,所以,當y的最高位二進位制位大於x的最高位就用看了,我們只需要從1到 x << 1列舉就行了,如果m比x小就1 到 m
// Problem: B. Shohag Loves Strings
// Contest: Codeforces - CodeTON Round 9 (Div. 1 + Div. 2, Rated, Prizes!)
// URL: https://codeforces.com/contest/2039/problem/B
// Memory Limit: 256 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
//by codeforcer ——
// ____ _ _ _ _ _ _ ____ _
// / ___|| | | || | | || | | | |___ \ | |
//| | | |_| || |_| || |_| | __) | | |
//| | | _ || _ || _ | |__ < | |
//| |___ | | | || | | || | | | ___) | | |
// \____||_| |_||_| |_||_| |_| |____ / |_|
#include<bits/stdc++.h>
using namespace std;
typedef int E;
typedef long long LL;
typedef pair<int, int> PII;
typedef tuple<int, int, int> PIII;
typedef tuple<LL, LL, LL> PLLL;
typedef pair<long long, long long> PLL;
typedef unsigned long long ULL;
#define endl '\n'
#define vec vector
#define pb push_back
#define pob pop_back
#define fir first
#define sec second
#define maxINT 0x3f3f3f3f
#define maxLL 0x3f3f3f3f3f3f3f3fLL
#define umap unordered_map
#define uset unordered_set
#define maxheap priority_queue<E, vector<E>, less<E>>
#define minheap priority_queue<E, vector<E>, greater<E>>
#define prvec(a) \
for (int i = 0; i < (a).size(); i++) { \
cout << (a)[i] << " "; \
} \
cout << endl;
#define debug0(a) \
cout << #a << ": "; \
for (int k = 0; k < (a).size(); k++) { \
cout << (a)[k] << " "; \
} \
cout << endl;
#define debug1(a) \
cout << #a << ": "; \
for (int k = 1; k <= (a).size(); k++) { \
cout << (a)[k] << " "; \
} \
cout << endl;
LL gcd(LL a, LL b) { return (b) ? gcd(b, a % b) : a; }
LL exgcd(LL a, LL b, LL &x, LL &y) {if (b == 0) { x = 1, y = 0; return a; }LL gcd = exgcd(b, a % b, y, x);y -= a / b * x;return gcd;}
LL qmi(LL a, LL b, LL mod) {LL res = 1;while (b) {if (b & 1) res = res * a % mod;a = a * a % mod;b >>= 1;}return res;}
const int N = 200010;
void solve()
{
long long a,b;
cin>>a>>b;
long long ans = 0;
int end = min(b,a << 1); // 列舉邊界
for(int i = 1;i <= end;i ++)
{
if(i == a) continue;
int number = i ^ a;
if(a % number == 0 || i % number == 0)
{
ans ++;
}
}
cout<<ans<<endl;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n;cin>>n;while(n --)
solve();
return 0;
}
D. Shohag Loves GCD
Shohag有一個整數n和一個包含m個唯一整數的集合S。幫助他找到字典序最大的整數陣列a1,a2,…,an,使得對於每個1≤i≤n,ai∈S,並且對於所有滿足1≤i<j≤n的數對,滿足gcd(i,j)≠gcd(ai,aj),或者說明不存在這樣的陣列。∗∗一個陣列aa在長度相同的情況下比陣列bb字典序更大,如果a≠ba≠b,且在a和b第一次出現不同的位置,陣列a對應的元素比b中對應的元素大。†gcd(x,y)表示整數xx和y的最大公約數(GCD)。
既然要求我們讓輸出的陣列字典序最大,那麼我們就從最大字典序的情況開始第一個樣例:
6 3
3 4 6
我們讓答案陣列ans是6 6 6 6 6 6
這樣輸出肯定是不行的,我們再看題目給的要求:對於所有滿足1≤i<j≤n的數對,滿足gcd(i,j)≠gcd(ai,aj)
我們從前往後遍歷,列舉所有下標 j 只要前面從1到 j 的所有下表都滿足 gcd(i,j)≠gcd(ai,aj),如果有一個不滿足,我們就讓\(a_j\) 等於集合中第一個小於\(a_i\) 的數 我們到最後得到的陣列就是字典序最大的。
我們假設 j = 2 ,那麼有可能會讓 gcd(i,j)≠gcd(ai,aj) 不成立的數只有下標 1
假設j = 3,那麼有可能讓這個性質不成立的下標有1 ,因為1 2 兩個數對 3 的最大公約數都是1
假設j = 4,那麼列舉之前所有下標gcd(1,4) = 1 gcd(2,4) = 2 gcd(3,4) = 1 可能讓題目性質不成立的下標有下標1 下標2
假設j = 6,gcd(1,6) = 1,gcd(2,6) = 2 gcd(3,6) = 3 ,gcd(4,6) = 2,gcd(5,6) = 1
假設j = 8,gcd(1,8) = 1,gcd(2,8) = 2,gcd(3,8) = 1,gcd(4,8) = 4 ,gcd(5,8) = 1,gcd(6,8) = 2 ,gcd(7,8) = 1
j = 2 : 1
j = 3:1
j = 4:1 2
j = 6:1 2 3
j = 8:1 2 4
我們可以發現,所有對j有影響的下標都是j的約數,如果我們每次進入一個下標就求一次一個下標的所有約數是會超時的,我們又可以發現,當我們j = 2是最大約數是1,j = 4時最大約數是2,j = 8時最大約數是4,只要j下標的值不同於j的最大約數這個下標就行了,求最大約數我們只需要找到j的最小質因子p,然後最大約數就是j / p,我們讓a[j]的值是a[p] 在集合s中第一個小於a[p]的值即可,如果沒用比a[p]更小的值,那麼就不能構造這個答案陣列,輸出-1
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define vec vector
//vector<LL> dist;
vector<bool> st;
void add(int a, int b, int c)
{
// graph[a].emplace_back(b, c);//
}
vector<int> zalgo(string s)
{
int n = s.size();
vector<int> z(n + 1, 0);
z[0] = n;
int i = 1, j = 1;
for (; i < n;i ++)
{
z[i] = max(0,min(j + z[j] - i,z[i - j]));
while (i + z[i] < n && s[z[i]] == s[i + z[i]])
z[i]++;
if(z[i] + i > z[j] + j)
j = i;
}
return z;
}
//void dijkstra()
//{
// minheap heap;
// dist[1] = 0;
// heap.push({0, 1});
// while (heap.size())
// {
// auto x = heap.top();
// heap.pop();
// int val = x.fir, site = x.sec;
// if (st[site])
// continue;
// st[site] = true;
// for (auto x : graph[site])
// {
// int end = x.first, len = x.second;
// if (dist[end] > dist[site] + len)
// {
// dist[end] = dist[site] + len;
// heap.push({dist[end], end});
// }
// } //
// }
//}
vector<int> minp, primes; // minp[i] 是i的最小質因子 primes是裝的1 ~ n的所有質數
void sieve(int n) //質數篩
{
minp.assign(n + 1, 0);
primes.clear();
for (int i = 2; i <= n; i++)
{
if (minp[i] == 0)
{
minp[i] = i;
primes.push_back(i);
}
for (auto p : primes)
{
if (i * p > n)
break;
minp[i * p] = p;
if (p == minp[i])
break;
}
}
}
void solve()
{
int n, m;
cin >> n >> m;
vec<int> a(m + 1,0);
map<int, int> mp; // 記錄一個數在集合中的下標方便找數
int x;
for (int i = 1; i <= m; i++)
{
cin >> x;
a[i] = x;
}
sort(a.begin() + 1, a.end());
for (int k = 1; k <= m; k++)
{
mp[a[k]] = k;
}
vector<int> ans(n + 1, *prev(a.end()));
for (int i = 2; i <= n; i++)
{
int p = minp[i], pos = 1;
p = i / p;//用最小質因子求出最大約數
pos = mp[ans[p]] - 1;//求出在集合s中第一個小於a[p]的數的下標
if (pos <= 0) // 如果下標小於等於0說明沒有數小於a[p]了
{
cout << -1 << endl;
return;
}
ans[i] = a[pos];//讓a[i] 是第一個小於a[p]的數
}
for (int i = 1; i <= n; i++)
{
cout << ans[i] << " ";
}
cout << endl;
}
int main()
{
sieve(1e5 + 10);
int n;
cin >> n;
for(int i = 1;i <= n;i ++)
{
solve();
}
return 0;
}