[Codeforces] number theory (R1200) Part.6
题单:https://codeforces.com/problemset/page/6?tags=number%20theory,0-1200
1245A. Good ol’ Numbers Coloring
原题指路:https://codeforces.com/problemset/problem/1245/A
题意
给定两整数 a , b a,b a,b.现对自然数集从小到大依次染色.设当前染到数字 i i i,规则如下:
①若 i = 0 i=0 i=0,将其染为白色.
②若 i ≥ a i\geq a i≥a且 i − a i-a i−a是白色,则将 i i i染为白色.
③若 i ≥ b i\geq b i≥b且 i − b i-b i−b是白色,则将 i i i染为白色.
④若 i i i还未被染色,将其染为黑色.
问最终被染成黑色的数的个数是否有限,若是则输出"Finite";否则输出"Infinite".
有 t ( 1 ≤ t ≤ 100 ) t\ \ (1\leq t\leq 100) t (1≤t≤100)组测试数据.每组测试数据输入两个整数 a , b ( 1 ≤ a , b ≤ 1 e 4 ) a,b\ \ (1\leq a,b\leq 1\mathrm{e}4) a,b (1≤a,b≤1e4).
思路
注意到被染成白色的数有形式 a x + b y ax+by ax+by.
(1)若 gcd ( a , b ) ≠ 1 \gcd(a,b)\neq 1 gcd(a,b)=1,则黑色的个数是无限的,因为能表示为 a x + b y ax+by ax+by的数是 gcd ( a , b ) \gcd(a,b) gcd(a,b)的倍数,则相邻两白色的数之间至少有一个黑色的数.
(2)若 gcd ( a , b ) = 1 \gcd(a,b)=1 gcd(a,b)=1,则黑色的个数是有限的.下面证明 > a b >ab >ab的数都会被染成白色.
设 x > a b x>ab x>ab.考察集合 S = { x , x − a , x − 2 a , ⋯ , x − ( b − 1 ) a } S=\{x,x-a,x-2a,\cdots,x-(b-1)a\} S={x,x−a,x−2a,⋯,x−(b−1)a}.
①若 S S S中的元素都是 b b b的倍数,则 b ∣ ( x − a ) , b ∣ ( x − 2 a ) b\mid (x-a),b\mid (x-2a) b∣(x−a),b∣(x−2a),进而 b ∣ a b\mid a b∣a,又 b ∣ ( x − a ) b\mid (x-a) b∣(x−a),则 b ∣ x b\mid x b∣x.
这表明: ∀ x > a b \forall x>ab ∀x>ab都是 b b b的倍数,则它们都会被染成白色.
②若 S S S中的元素不全是 b b b的倍数,由抽屉原理: ∃ x − s a , x − t a ∈ S s . t . x − s a ≡ x − t a ( m o d b ) \exist x-sa,x-ta\in S\ s.t.\ x-sa\equiv x-ta\ \ (\mathrm{mod}\ b) ∃x−sa,x−ta∈S s.t. x−sa≡x−ta (mod b).
则 b ∣ ( x − s a ) − ( x − t a ) = a ( t − s ) b\mid (x-sa)-(x-ta)=a(t-s) b∣(x−sa)−(x−ta)=a(t−s).不妨设 s < t s<t s<t.因 gcd ( a , b ) = 1 \gcd(a,b)=1 gcd(a,b)=1,则 b ∣ ( t − s ) > 0 b\mid (t-s)>0 b∣(t−s)>0.
而 t − s ≤ t < b t-s\leq t<b t−s≤t<b,矛盾.故 S S S中的元素都是 b b b的倍数.
代码
void solve() {
int a, b; cin >> a >> b;
cout << (gcd(a, b) == 1 ? "Finite" : "Infinite") << endl;
}
int main() {
CaseT // 单测时注释掉该行
solve();
}
1277B. Make Them Odd
原题指路:https://codeforces.com/problemset/problem/1277/B
题意 ( 3 s 3\ \mathrm{s} 3 s)
给定一个长度为 n n n的序列 a 1 , ⋯ , a n a_1,\cdots,a_n a1,⋯,an,每次可选择其中的一个偶数 x x x,将序列中所有等于 x x x的数除以 2 2 2.问至少经多少次操作后序列中只有奇数.
有 t ( 1 ≤ t ≤ 1 e 4 ) t\ \ (1\leq t\leq 1\mathrm{e}4) t (1≤t≤1e4)组测试数据.每组测试数据第一行输入一个整数 n ( 1 ≤ n ≤ 2 e 5 ) n\ \ (1\leq n\leq 2\mathrm{e}5) n (1≤n≤2e5).第二行输入 n n n个整数 a 1 , ⋯ , a n ( 1 ≤ a i ≤ 1 e 9 ) a_1,\cdots,a_n\ \ (1\leq a_i\leq 1\mathrm{e}9) a1,⋯,an (1≤ai≤1e9).数据保证所有测试数据的 n n n之和不超过 2 e 5 2\mathrm{e}5 2e5.
思路
显然应先删除较大的偶数.用一个set维护当前序列中的偶数,每次取最大的元素扩展即可.
代码
void solve() {
int n; cin >> n;
set<int> s;
while (n--) {
int x; cin >> x;
if (x % 2 == 0) s.insert(x);
}
int ans = 0;
while (s.size()) {
int tmp = *s.rbegin(); s.erase(tmp);
if (tmp % 2 == 0) {
ans++;
s.insert(tmp / 2);
}
}
cout << ans << endl;
}
int main() {
CaseT // 单测时注释掉该行
solve();
}
1312A. Two Regular Polygons
原题指路:https://codeforces.com/problemset/problem/1312/A
题意
给定一个凸正 n n n边形 A A A,问是否能以 A A A的某些顶点为顶点,构造一个中心与 A A A重合的凸正 m ( m < n ) m\ \ (m<n) m (m<n)边形 B B B,若能则输出"YES";否则输出"NO".
有 t ( 1 ≤ t ≤ 1 e 4 ) t\ \ (1\leq t\leq 1\mathrm{e}4) t (1≤t≤1e4)组测试数据.每组测试数据输入两个整数 n , m ( 3 ≤ m < n ≤ 100 ) n,m\ \ (3\leq m<n\leq 100) n,m (3≤m<n≤100).
思路
若有解,显然应等间距地选择 A A A的顶点,故有解的充要条件是: m ∣ n m\mid n m∣n.
代码
void solve() {
int n, m; cin >> n >> m;
cout << (n % m ? "NO" : "YES") << endl;
}
int main()
CaseT // 单测时注释掉该行
solve();
}
1324A. Yet Another Tetris Problem
原题指路:https://codeforces.com/problemset/problem/1324/A
题意 ( 2 s 2\ \mathrm{s} 2 s)
给定一个长度为 n n n的序列 a 1 , ⋯ , a n a_1,\cdots,a_n a1,⋯,an.当 ∃ a i > 0 \exists a_i>0 ∃ai>0时,有操作:①选择一个下标 i ( 1 ≤ i ≤ n ) i\ \ (1\leq i\leq n) i (1≤i≤n),令 a i + = 2 a_i+=2 ai+=2;②若所有 a i > 0 a_i>0 ai>0,令所有 a i − = 1 a_i-=1 ai−=1.问若干次操作后能否使得所有 a i ( 1 ≤ i ≤ n ) a_i\ \ (1\leq i\leq n) ai (1≤i≤n)变为 0 0 0,若能则输出"YES";否则输出"NO".
有 t ( 1 ≤ t ≤ 100 ) t\ \ (1\leq t\leq 100) t (1≤t≤100)组测试数据.每组测试数据第一行输入一个整数 n ( 1 ≤ n ≤ 100 ) n\ \ (1\leq n\leq 100) n (1≤n≤100).第二行输入 n n n个整数 a 1 , ⋯ , a n ( 1 ≤ a i ≤ 100 ) a_1,\cdots,a_n\ \ (1\leq a_i\leq 100) a1,⋯,an (1≤ai≤100).
思路
因操作①不改变 a i a_i ai的奇偶性,操作②同时改变所有 a i a_i ai的奇偶性,故有解的充要条件是:初始时各 a i a_i ai的奇偶性相同.
代码
void solve() {
int n; cin >> n;
vi a(n);
for (auto& ai : a) {
int x; cin >> x;
ai = x & 1;
}
cout << (a == vi(n, a[0]) ? "YES" : "NO") << endl;
}
int main() {
CaseT // 单测时注释掉该行
solve();
}
1325A. EhAb AnD gCd
原题指路:https://codeforces.com/problemset/problem/1325/A
题意
给定一个整数 x x x,求任一个整数对 ( a , b ) s . t . gcd ( a , b ) + l c m ( a , b ) = x (a,b)\ s.t.\ \gcd(a,b)+\mathrm{lcm}(a,b)=x (a,b) s.t. gcd(a,b)+lcm(a,b)=x.数据保证有解.
有 t ( 1 ≤ t ≤ 100 ) t\ \ (1\leq t\leq 100) t (1≤t≤100)组测试数据.每组测试数据输入一个整数 x ( 2 ≤ x ≤ 1 e 9 ) x\ \ (2\leq x\leq 1\mathrm{e}9) x (2≤x≤1e9).
思路
注意到 gcd ( 1 , x − 1 ) + l c m ( 1 , x − 1 ) = 1 + ( x − 1 ) = x \gcd(1,x-1)+\mathrm{lcm}(1,x-1)=1+(x-1)=x gcd(1,x−1)+lcm(1,x−1)=1+(x−1)=x.
代码
void solve() {
int x; cin >> x;
cout << 1 << ' ' << x - 1 << endl;
}
int main() {
CaseT // 单测时注释掉该行
solve();
}
1326A. Bad Ugly Numbers
原题指路:https://codeforces.com/problemset/problem/1326/A
题意
给定一个整数 n n n,问是否存在满足下列条件的整数 s s s:① s > 0 s>0 s>0;② s s s的十进制表示有 n n n位;③ s s s的任一数码非零;④ s s s不被任一它的数码整除.若存在,输出任一符合条件的 s s s;否则输出 − 1 -1 −1.
有 t ( 1 ≤ t ≤ 400 ) t\ \ (1\leq t\leq 400) t (1≤t≤400)组测试数据.每组测试数据第一行输入一个整数 n ( 1 ≤ n ≤ 1 e 5 ) n\ \ (1\leq n\leq 1\mathrm{e}5) n (1≤n≤1e5).数据保证所有测试样的 n n n之和不超过 1 e 5 1\mathrm{e}5 1e5.
思路
① n = 1 n=1 n=1时,显然无解.
② n ≥ 2 n\geq 2 n≥2时,易想到用数码 2 2 2和 3 3 3构造一个奇数,这样可保证该数不能被 2 2 2整除.
考虑如何保证该数不被 3 3 3整除,显然可构造数 23 ⋯ 3 ‾ \overline{23\cdots 3} 23⋯3.
代码
void solve() {
int n; cin >> n;
if (n == 1) cout << -1 << endl;
else cout << 2 << string(n - 1, '3') << endl;
}
int main() {
CaseT // 单测时注释掉该行
solve();
}
1364A. XXXXX
原题指路:https://codeforces.com/problemset/problem/1364/A
题意
给定一个长度为 n n n的序列 a 1 , ⋯ , a n a_1,\cdots,a_n a1,⋯,an,问是否存在一个连续子列使得其中的元素之和不是 x x x的倍数,若存在,则输出最长连续子列的长度;否则输出 − 1 -1 −1.
有 t ( 1 ≤ t ≤ 5 ) t\ \ (1\leq t\leq 5) t (1≤t≤5)组测试数据.每组测试数据第一行输入两个整数 n , x ( 1 ≤ n ≤ 1 e 5 , 1 ≤ x ≤ 1 e 4 ) n,x\ \ (1\leq n\leq 1\mathrm{e}5,1\leq x\leq 1\mathrm{e}4) n,x (1≤n≤1e5,1≤x≤1e4).第二行输入 n n n个整数 a 1 , ⋯ , a n ( 0 ≤ a i ≤ 1 e 4 ) a_1,\cdots,a_n\ \ (0\leq a_i\leq 1\mathrm{e}4) a1,⋯,an (0≤ai≤1e4).
思路
显然最优解是某个前缀或某个后缀,检查每个前缀和后缀是否满足要求即可,用前缀和优化.
代码
void solve() {
int n, x; cin >> n >> x;
vi a(n + 1), pre(n + 1, 0);
for (int i = 1; i <= n; i++) {
cin >> a[i];
pre[i] = pre[i - 1] + a[i];
}
int ans = -1;
for (int l = 1; l <= n; l++) {
if ((pre[n] - pre[l - 1]) % x) {
ans = max(ans, n - l + 1);
break;
}
}
for (int r = n; r >= 1; r--) {
if (pre[r] % x) {
ans = max(ans, r);
break;
}
}
cout << ans << endl;
}
int main() {
CaseT // 单测时注释掉该行
solve();
}
1370A. Maximum GCD
原题指路:https://codeforces.com/problemset/problem/1370/A
题意
在 [ 1 , n ] [1,n] [1,n]中选两个相异的整数使得它们的 gcd \gcd gcd最大,输出最大的 gcd \gcd gcd.
有 t ( 1 ≤ t ≤ 100 ) t\ \ (1\leq t\leq 100) t (1≤t≤100)组测试数据.每组测试数据输入一个整数 n ( 2 ≤ n ≤ 1 e 6 ) n\ \ (2\leq n\leq 1\mathrm{e}6) n (2≤n≤1e6).
思路
若 gcd \gcd gcd的最大值能取到 d d d,则至少 2 d ≤ n 2d\leq n 2d≤n,故 gcd \gcd gcd的最大值即 ⌊ n 2 ⌋ \left\lfloor\dfrac{n}{2}\right\rfloor ⌊2n⌋.
代码
void solve() {
int n; cin >> n;
cout << n / 2 << endl;
}
int main() {
CaseT // 单测时注释掉该行
solve();
}
1370B. GCD Compression
原题指路:https://codeforces.com/problemset/problem/1370/B
题意
给定一个长度为 2 n 2n 2n的序列 a 1 , ⋯ , a 2 n a_1,\cdots,a_{2n} a1,⋯,a2n,现要将其压缩成一个长度为 ( n − 1 ) (n-1) (n−1)的序列 b [ ] b[] b[],先删去 a [ ] a[] a[]中的任意两元素,再进行如下操作:选择 a [ ] a[] a[]中的两元素,将它们之和加入序列 b [ ] b[] b[],并将它们从 a [ ] a[] a[]中删除.构造任一个选择方案使得最终得到的序列 b [ ] b[] b[]中所有元素的 gcd > 1 \gcd>1 gcd>1.
有 t ( 1 ≤ t ≤ 10 ) t\ \ (1\leq t\leq 10) t (1≤t≤10)组测试数据.每组测试数据第一行输入一个整数 n ( 2 ≤ n ≤ 1000 ) n\ \ (2\leq n\leq 1000) n (2≤n≤1000).第二行输入 2 n 2n 2n个整数 a 1 , ⋯ , a 2 n ( 1 ≤ a i ≤ 1000 ) a_1,\cdots,a_{2n}\ \ (1\leq a_i\leq 1000) a1,⋯,a2n (1≤ai≤1000).
对每组测试数据输出 ( n − 1 ) (n-1) (n−1)行,其中第 i i i行输入两个整数 i , j ( 1 ≤ i , j ≤ 2 n , i ≠ j ) i,j\ \ (1\leq i,j\leq 2n,i\neq j) i,j (1≤i,j≤2n,i=j),表示将 a i + a j a_i+a_j ai+aj加入序列 b [ ] b[] b[]并删除 a i a_i ai和 a j a_j aj.删去 a [ ] a[] a[]中的任意两元素无需输出.数据保证有解.
思路
考虑使得最终得到的序列 b [ ] b[] b[]中所有元素的 gcd = 2 \gcd=2 gcd=2.
①若序列 a [ ] a[] a[]中有偶数个奇数,显然有解.
②若序列 a [ ] a[] a[]中有奇数个奇数,可初始时删除一个奇数和一个偶数,化为情况①.
代码
void solve() {
int n; cin >> n;
vi odd, even;
for (int i = 1; i <= 2 * n; i++) {
int a; cin >> a;
if (a & 1) odd.push_back(i);
else even.push_back(i);
}
vii ans;
for (int i = 0; i + 1 < odd.size(); i += 2) ans.push_back({ odd[i],odd[i + 1] });
for (int i = 0; i + 1 < even.size(); i += 2) ans.push_back({ even[i],even[i + 1] });
for (int i = 0; i < n - 1; i++) cout << ans[i].first << ' ' << ans[i].second << endl;
}
int main() {
CaseT // 单测时注释掉该行
solve();
}
1388A. Captain Flint and Crew Recruitment
原题指路:https://codeforces.com/problemset/problem/1388/A
题意
称一个正整数 x x x是nearly prime的,如果 ∃ 1 < p < q , p , q ∈ p r i m e s s . t . x = p q \exists 1<p<q,p,q\in primes\ s.t.\ x=pq ∃1<p<q,p,q∈primes s.t. x=pq.给定一个正整数 n n n,问能否将其表示为 4 4 4个正整数之和,其中至少 3 3 3个数是nearly prime的.
有 t ( 1 ≤ t ≤ 1000 ) t\ \ (1\leq t\leq 1000) t (1≤t≤1000)组测试数据.每组测试数据输入一个整数 n ( 1 ≤ n ≤ 2 e 5 ) n\ \ (1\leq n\leq 2\mathrm{e}5) n (1≤n≤2e5).
对每组测试数据,若有解,输出"YES"并输出任一组解;否则输出"NO".
思路
最小的四个nearly prime的数是 6 , 10 , 14 , 15 6,10,14,15 6,10,14,15.
①若 n ≤ 30 = 6 + 10 + 14 n\leq 30=6+10+14 n≤30=6+10+14,则无解.
②若 n > 30 n>30 n>30,则 n = 6 + 10 + 14 + ( n − 30 ) n=6+10+14+(n-30) n=6+10+14+(n−30).
注意特判 n − 30 = 6 , 10 , 14 n-30=6,10,14 n−30=6,10,14,即 n = 36 , 40 , 44 n=36,40,44 n=36,40,44的情况,此时可输出 6 , 10 , 15 , n − 31 6,10,15,n-31 6,10,15,n−31.
代码
void solve() {
int n; cin >> n;
if (n <= 30) {
cout << "NO" << endl;
return;
}
cout << "YES" << endl;
if (n == 36 || n == 40 || n == 44) cout << "6 10 15 " << n - 31 << endl;
else cout << "6 10 14 " << n - 30 << endl;
}
int main() {
CaseT // 单测时注释掉该行
solve();
}