[Codeforces] number theory (R1600) Part.8
题单:https://codeforces.com/problemset/page/1?tags=number+theory%2C1201-1600
1242A. Tile Painting
原题指路:https://codeforces.com/problemset/problem/1242/A
题意
编号1∼n1\sim n1∼n的nnn的格子排成一行.现对这些格子染色,定义一种染色方案是好的,如果对∀i,j (i≠j) s.t. ∣j−i∣\forall i,j\ \ (i\neq j)\ s.t.\ |j-i|∀i,j (i=j) s.t. ∣j−i∣是nnn的一个>1>1>1的约数,则它们颜色相同.给定n (1≤n≤1e12)n\ \ (1\leq n\leq 1\mathrm{e}12)n (1≤n≤1e12),问至多能用多少种颜色染色,使得染色方案是好的.
思路
①若n=pk (p∈primes)n=p^k\ \ (p\in primes)n=pk (p∈primes),因nnn模ppp有ppp种余数,故ans=pans=pans=p.
②若n=pq (p,q>1)n=pq\ \ (p,q>1)n=pq (p,q>1)且gcd(p,q)=1\gcd(p,q)=1gcd(p,q)=1,则ans=1ans=1ans=1.
[证] 对∀i,j (i≠j)\forall i,j\ \ (i\neq j)∀i,j (i=j),由CRT:∃x∈[1,n] s.t. x≡i (mod p),x≡j (mod p)\exists x\in[1,n]\ s.t.\ x\equiv i\ \ (\mathrm{mod}\ p),x\equiv j\ \ (\mathrm{mod}\ p)∃x∈[1,n] s.t. x≡i (mod p),x≡j (mod p),
则下标i,ji,ji,j与下标xxx颜色相同,进而所有格子颜色相同.
代码
void solve() {
ll n; cin >> n;
for (int d = 2; (ll)d * d <= n; d++) {
if (n % d == 0) {
while (n % d == 0) n /= d;
if (n > 1) {
cout << 1;
return;
}
else {
cout << d;
return;
}
}
}
cout << n;
}
int main() {
solve();
}
1263C. Everyone is a Winner!
原题指路:https://codeforces.com/problemset/problem/1263/C
题意
有t (1≤t≤10)t\ \ (1\leq t\leq 10)t (1≤t≤10)组测试数据.每组测试数据输入一个整数n (1≤n≤1e9)n\ \ (1\leq n\leq 1\mathrm{e}9)n (1≤n≤1e9).对所有正整数kkk,问⌊nk⌋\left\lfloor\dfrac{n}{k}\right\rfloor⌊kn⌋有多少种不同的取值,第一行输出不同取值的个数,第二行升序输出所有取值.
思路
所有0≤x<⌊n⌋0\leq x<\left\lfloor\sqrt{n}\right\rfloor0≤x<⌊n⌋都是解.
[证] 方程⌊nk⌋=x\left\lfloor\dfrac{n}{k}\right\rfloor=x⌊kn⌋=x等价于x≤nk<x+1x\leq\dfrac{n}{k}<x+1x≤kn<x+1,解得k∈(nx+1,nx]k\in\left(\dfrac{n}{x+1},\dfrac{n}{x}\right]k∈(x+1n,xn],区间长度为nx2+x\dfrac{n}{x^2+x}x2+xn.
注意到x<⌊n⌋x<\left\lfloor\sqrt{n}\right\rfloorx<⌊n⌋时,nx2+x>1\dfrac{n}{x^2+x}>1x2+xn>1,则区间内至少存在一个整数k=⌊nx⌋k=\left\lfloor\dfrac{n}{x}\right\rfloork=⌊xn⌋,故所有x∈[0,⌊n⌋)x\in\left[0,\left\lfloor\sqrt{n}\right\rfloor\right)x∈[0,⌊n⌋)都是解.
整除分块求所有解即可.
代码
void solve() {
int n; cin >> n;
vi ans;
for (int l = 1, r, t; l <= n; l = r + 1) {
r = (t = n / l) ? min(n / t, n) : n;
ans.push_back(n / l);
}
ans.push_back(0);
reverse(all(ans)); // 注意翻转
cout << ans.size() << endl;
for (int i : ans) cout << i << ' ';
cout << endl;
}
int main() {
CaseT // 单测时注释掉该行
solve();
}
1266C. Diverse Matrix
原题指路:https://codeforces.com/problemset/problem/1266/C
题意
设AAA是一个r×cr\times cr×c的整型矩阵,其中元素未必不同.构造一个长度为(r+c)(r+c)(r+c)的序列b[]b[]b[],其中前rrr个元素是AAA每行的gcd\gcdgcd,后ccc个元素是AAA每列的gcd\gcdgcd.称序列b[]b[]b[]是好的,如果其中的元素两两相异.定义好的序列的权值为其中元素的最大值.
给定两整数rrr和c (1≤r,c≤500)c\ \ (1\leq r,c\leq 500)c (1≤r,c≤500),构造一个r×cr\times cr×c矩阵AAA使得其产生的序列b[]b[]b[]是好的,且其权值最小.无解输出000.若有多组解,输出任一组解.
思路
①r=c=1r=c=1r=c=1时无解.
②r=1r=1r=1时,最优解为A=[2 3 ⋯ c+1]A=[2\ 3\ \cdots\ c+1]A=[2 3 ⋯ c+1],不取1∼c1\sim c1∼c是因为111会重复.
③c=1c=1c=1时,最优解为A=[2 3 ⋯ c+1]TA=[2\ 3\ \cdots\ c+1]^TA=[2 3 ⋯ c+1]T.
④r,c≥2r,c\geq 2r,c≥2时,令aij=i(j+r)a_{ij}=i(j+r)aij=i(j+r),则bi=gcd{i(r+1),⋯ ,i(r+c)}=i⋅gcd{r+1,⋯ ,r+c}=ib_i=\gcd\{i(r+1),\cdots,i(r+c)\}=i\cdot \gcd\{r+1,\cdots,r+c\}=ibi=gcd{i(r+1),⋯,i(r+c)}=i⋅gcd{r+1,⋯,r+c}=i.
此时b[]b[]b[]的权值为(r+c)(r+c)(r+c),显然这是最小的.
代码
void solve() {
int r, c; cin >> r >> c;
if (r * c == 1) {
cout << 0;
return;
}
if (r == 1) {
for (int i = 2; i <= c + 1; i++) cout << i << ' ';
return;
}
else if (c == 1) {
for (int i = 2; i <= r + 1; i++) cout << i << endl;
return;
}
for (int i = 1; i <= r; i++)
for (int j = 1; j <= c; j++) cout << i * (j + r) << " \n"[j == c];
}
int main() {
solve();
}
1285C. Fadi and LCM
原题指路:https://codeforces.com/problemset/problem/1285/C
题意
给定一个整数x (1≤x≤1e12)x\ \ (1\leq x\leq 1\mathrm{e}12)x (1≤x≤1e12),求两正整数a,b s.t. lcm(a,b)=xa,b\ s.t.\ \mathrm{lcm}(a,b)=xa,b s.t. lcm(a,b)=x且max{a,b}\max\{a,b\}max{a,b}最小.若有多组解,输出任一组.
思路I
将xxx素因数分解后,枚举将素因子分配给aaa和bbb的所有方案,求max{a,b}\max\{a,b\}max{a,b}的最小值.
代码I
vl factors;
void get(ll n) { // 对x素因数分解
for (ll d = 2; d * d <= n; d++) {
if (n % d == 0) {
ll cur = 1;
while (n % d == 0) n /= d, cur *= d;
factors.push_back(cur);
}
}
if (n > 1) factors.push_back(n);
}
void solve() {
ll x; cin >> x;
get(x);
ll ansa = INFF, ansb = INFF;
int n = factors.size();
for (int i = 0; i < (1 << n); i++) {
ll a = 1, b = 1;
for (int j = 0; j < n; j++) {
if (i >> j & 1) a *= factors[j];
else b *= factors[j];
}
if (max(a, b) < max(ansa, ansb)) ansa = a, ansb = b;
}
cout << ansa << ' ' << ansb;
}
int main() {
solve();
}
思路II
枚举xxx的约数ddd,检查是否有lcm(d,xd)=x\mathrm{lcm}\left(d,\dfrac{x}{d}\right)=xlcm(d,dx)=x,更新max{a,b}\max\{a,b\}max{a,b}的最小值.
代码II
void solve() {
ll x; cin >> x;
ll ans = 0;
for (ll d = 1; d * d <= x; d++)
if (x % d == 0 && lcm(d, x / d) == x) ans = d;
cout << ans << ' ' << x / ans;
}
int main() {
solve();
}
1294C. Product of Three Numbers
原题指路:https://codeforces.com/problemset/problem/1294/C
题意 (2 s)(2\ \mathrm{s})(2 s)
有t (1≤t≤100)t\ \ (1\leq t\leq 100)t (1≤t≤100)组测试数据.每组测试数据输入一个整数n (2≤n≤1e9)n\ \ (2\leq n\leq 1\mathrm{e}9)n (2≤n≤1e9).求三个相异的正整数a,b,c s.t. a,b,c≥2a,b,c\ s.t.\ a,b,c\geq 2a,b,c s.t. a,b,c≥2且n=abcn=abcn=abc,若有解则第一行输出"YES",第二行输出任一组解;否则输出"NO".
思路
不妨设a<b<ca<b<ca<b<c,下面最小化aaa并最大化ccc.设aaa是nnn的>1>1>1的最小约数,bbb是na\dfrac{n}{a}an的非aaa的>1>1>1的最小约数,若nab≠a,b,1\dfrac{n}{ab}\neq a,b,1abn=a,b,1,则找到一组解.
代码
void solve() {
int n; cin >> n;
uset<int> s;
for (int d = 2; (ll)d * d <= n; d++) { // 求n的>1的最小约数a
if (n % d == 0) {
n /= d;
s.insert(d);
break;
}
}
for (int d = 2; (ll)d * d <= n; d++) { // 求n/a的非a的>1的最小约数b
if (n % d == 0 && !s.count(d)) {
n /= d;
s.insert(d);
break;
}
}
if (s.size() < 2 || s.count(n) || n == 1) cout << "NO" << endl;
else {
cout << "YES" << endl;
s.insert(n);
for (auto i : s) cout << i << ' ';
cout << endl;
}
}
int main() {
CaseT // 单测时注释掉该行
solve();
}
1305C. Kuroni and Impossible Calculation
原题指路:https://codeforces.com/problemset/problem/1305/C
题意
给定一个长度为n (2≤n≤2e5)n\ \ (2\leq n\leq 2\mathrm{e}5)n (2≤n≤2e5)的序列a1,⋯ ,an (0≤ai≤1e9)a_1,\cdots,a_n\ \ (0\leq a_i\leq 1\mathrm{e}9)a1,⋯,an (0≤ai≤1e9)和一个整数m (1≤m≤1000)m\ \ (1\leq m\leq 1000)m (1≤m≤1000),求∏1≤i<j≤n∣ai−aj∣\displaystyle \prod_{1\leq i<j\leq n}|a_i-a_j|1≤i<j≤n∏∣ai−aj∣,答案对mmm取模.
思路
①n≤mn\leq mn≤m时,暴力求即可.
②n>mn>mn>m时,因模mmm只有mmm种余数,则至少存在两个数ai,aj s.t. ai≡aj (mod m)a_i,a_j\ s.t.\ a_i\equiv a_j\ \ (\mathrm{mod}\ m)ai,aj s.t. ai≡aj (mod m),故ans=0ans=0ans=0.
代码
void solve() {
int n, m; cin >> n >> m;
vi a(n);
for (auto& ai : a) cin >> ai;
if (n > m) cout << 0;
else {
int ans = 1;
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++) ans = (ll)abs(a[i] - a[j]) % m * ans % m;
cout << ans;
}
}
int main() {
solve();
}
1312C. Adding Powers
原题指路:https://codeforces.com/problemset/problem/1312/C
题意 (2 s2\ \mathrm{s}2 s)
序列v1,⋯ ,vnv_1,\cdots,v_nv1,⋯,vn初始时都为零.现有操作:在第iii步(下标从000开始)时,可选择跳过此步,也可选择一个下标pos∈[1,n]pos\in[1,n]pos∈[1,n],令vpos+=kiv_{pos}+=k^ivpos+=ki.给定一个序列a1,⋯ ,ana_1,\cdots,a_na1,⋯,an,问若干次操作后能否将序列v[]v[]v[]变为序列a[]a[]a[],若能则输出"YES";否则输出"NO".
有t (1≤t≤1000)t\ \ (1\leq t\leq 1000)t (1≤t≤1000)组测试数据.每组测试数据第一行输入两个整数n,k (1≤n≤30,2≤k≤100)n,k\ \ (1\leq n\leq 30,2\leq k\leq 100)n,k (1≤n≤30,2≤k≤100).第二行输入nnn个整数a1,⋯ ,an (0≤ai≤1e16)a_1,\cdots,a_n\ \ (0\leq a_i\leq 1\mathrm{e}16)a1,⋯,an (0≤ai≤1e16).
思路
将每个aia_iai表示成kkk进制数,检查是否有相同的kkk的幂次.
代码
const int MAXN = 35;
int n, k;
ll a[MAXN];
bool check() {
uset<int> s; // 记录用过的k的幂次
for (int i = 0; i < n; i++) {
ll x = a[i];
int d = 0; // k的幂次
while (x) {
if (x % k != 0 && x % k != 1) return false;
if (x % k == 1) {
if (s.count(d)) return false;
s.insert(d);
}
d++;
x /= k;
}
}
return true;
}
void solve() {
cin >> n >> k;
for (int i = 0; i < n; i++) cin >> a[i];
cout << (check() ? "YES" : "NO") << endl;
}
int main() {
CaseT // 单测时注释掉该行
solve();
}
1332B. Composite Coloring
原题指路:https://codeforces.com/problemset/problem/1332/B
题意 (2 s)(2\ \mathrm{s})(2 s)
称一个正整数是好的,如果它能表示为两>1>1>1的正整数之积.称一个序列是好的,如果其所有元素都是好的.
给定一个长度为nnn的好的序列a1,⋯ ,ana_1,\cdots,a_na1,⋯,an.现选定一个正整数m∈[1,m]m\in[1,m]m∈[1,m],用编号1∼m1\sim m1∼m的mmm种颜色给序列染色,使得每种颜色至少用一次,序列中每个元素被染有且只有一种颜色,任意两个相同颜色的元素的gcd>1\gcd>1gcd>1.注意相等的元素可染不同色.可以证明当所有ai≤1000a_i\leq 1000ai≤1000时有解.构造任一组染色方案,第一行输出所用颜色的种数,第二行输出一个染色方案.
有t (1≤t≤1000)t\ \ (1\leq t\leq 1000)t (1≤t≤1000)组测试数据.每组测试数据第一行输入一个整数n (1≤n≤1000)n\ \ (1\leq n\leq 1000)n (1≤n≤1000).第二行输入一个长度为nnn的好的序列a1,⋯ ,an (4≤ai≤1000)a_1,\cdots,a_n\ \ (4\leq a_i\leq 1000)a1,⋯,an (4≤ai≤1000).数据保证所有测试数据的nnn之和不超过1e41\mathrm{e}41e4.
思路
对每个好的数kkk,存在一个素数p≤k s.t. p∣kp\leq \sqrt{k}\ s.t.\ p\mid kp≤k s.t. p∣k.因1000\sqrt{1000}1000以内共111111个素数,则每个数与其素因子染相同颜色即可.
代码
const int MAXN = 1005;
vi res[MAXN]; // 含有最小素因子p的元素的下标
int ans[MAXN];
int get(int x) { // 求x的最小素因子
for (int i = 2; i * i <= x; i++)
if (x % i == 0) return i;
return x;
}
void solve() {
int n; cin >> n;
for (int i = 1; i < MAXN; i++) res[i].clear();
for (int i = 1; i <= n; i++) {
int a; cin >> a;
res[get(a)].push_back(i);
}
int color = 0;
for (int i = 1; i < MAXN; i++) {
if (res[i].size()) {
color++;
for (auto j : res[i]) ans[j] = color;
}
}
cout << color << endl;
for (int i = 1; i <= n; i++) cout << ans[i] << " \n"[i == n];
}
int main() {
CaseT // 单测时注释掉该行
solve();
}
1342C. Yet Another Counting Problem
原题指路:https://codeforces.com/problemset/problem/1342/C
题意 (3.5 s)(3.5\ \mathrm{s})(3.5 s)
给定两整数a,ba,ba,b.现给定两整数l,rl,rl,r,表示询问有多少个x∈[l,r] s.t. (x mod a) mod b≠(x mod b) mod ax\in[l,r]\ s.t.\ (x\ \mathrm{mod}\ a)\ \mathrm{mod}\ b\neq (x\ \mathrm{mod}\ b)\ \mathrm{mod}\ ax∈[l,r] s.t. (x mod a) mod b=(x mod b) mod a.
有t (1≤t≤100)t\ \ (1\leq t\leq 100)t (1≤t≤100)组测试数据.每组测试数据第一行输入三个整数a,b,q (1≤a,b≤200,1≤q≤500)a,b,q\ \ (1\leq a,b\leq 200,1\leq q\leq 500)a,b,q (1≤a,b≤200,1≤q≤500),其中qqq表示询问书.接下来qqq行每行输入两个整数l,r (1≤l≤r≤1e18)l,r\ \ (1\leq l\leq r\leq 1\mathrm{e}18)l,r (1≤l≤r≤1e18),表示一个询问.
思路
注意到[(x+ab) mod a] mod b=(x mod a) mod b[(x+ab)\ \mathrm{mod}\ a]\ \mathrm{mod}\ b=(x\ \mathrm{mod}\ a)\ \mathrm{mod}\ b[(x+ab) mod a] mod b=(x mod a) mod b,则xxx有上述性质当且仅当x mod abx\ \mathrm{mod}\ abx mod ab有上述性质.
预处理出len=ablen=ablen=ab内满足所需性质的数的个数的前缀和pre[]pre[]pre[],根据⌊xlen⌋\left\lfloor\dfrac{x}{len}\right\rfloor⌊lenx⌋和x%lenx\% lenx%len求[1,x][1,x][1,x]中有多少个数满足所需性质.
代码
const int MAXN = 4e4 + 5;
int pre[MAXN]; // 满足所需性质的数的个数的前缀和
int len; // a*b
void init(int a,int b) {
len = a * b;
for (int i = 1; i <= len; i++)
pre[i] = pre[i - 1] + ((i % a) % b != (i % b) % a);
}
ll query(ll x) {
ll cnt = x / len, rest = x % len;
return cnt * pre[len] + pre[rest];
}
ll query(ll l, ll r) {
return query(r) - query(l - 1);
}
void solve() {
int a, b; cin >> a >> b;
init(a, b);
CaseT{
ll l, r; cin >> l >> r;
cout << query(l, r) << ' ';
}
cout << endl;
}
int main() {
CaseT // 单测时注释掉该行
solve();
}
1344A. Hilbert’s Hotel
原题指路:https://codeforces.com/problemset/problem/1344/A
题意
有无限个房间,其中编号0∼(n−1)0\sim (n-1)0∼(n−1)的nnn个房间分别住着客人a0,⋯ ,an−1a_0,\cdots,a_{n-1}a0,⋯,an−1.现有操作:对每个整数k∈[0,k−1]k\in[0,k-1]k∈[0,k−1],将kkk号房间的客人移动到(k+ak mod n)(k+a_{k\ \mathrm{mod}\ n})(k+ak mod n)号房间.问操作后0∼(n−1)0\sim (n-1)0∼(n−1)号房间是否有且只有一个客人.
有t (1≤t≤1e4)t\ \ (1\leq t\leq 1\mathrm{e}4)t (1≤t≤1e4)组测试数据.每组测试数据第一行输入一个整数n (1≤n≤2e5)n\ \ (1\leq n\leq 2\mathrm{e}5)n (1≤n≤2e5).第二行输入一个长度为nnn的序列a0⋯ ,an−1 (−1e9≤ai≤1e9)a_0\cdots,a_{n-1}\ \ (-1\mathrm{e}9\leq a_i\leq 1\mathrm{e}9)a0⋯,an−1 (−1e9≤ai≤1e9).数据保证所有测试数据的nnn之和不超过2e52\mathrm{e}52e5.
思路
0∼(n−1)0\sim (n-1)0∼(n−1)号房间是否有且只有一个客人等价于没有两个客人在同一房间且没有空房间.
设操作后存在两个客人在同一房间,则x+ax mod n=y+ay mod nx+a_{x\ \mathrm{mod}\ n}=y+a_{y\ \mathrm{mod}\ n}x+ax mod n=y+ay mod n至少有一整数解.
设x=k1n+i,y=k2n+jx=k_1n+i,y=k_2n+jx=k1n+i,y=k2n+j,则原方程⇔x−y=ay mod n−ax mod n⇔k1n+i−k2n−j=aj−ai\Leftrightarrow x-y=a_{y\ \mathrm{mod}\ n}-a_{x\ \mathrm{mod}\ n}\Leftrightarrow k_1n+i-k_2n-j=a_j-a_i⇔x−y=ay mod n−ax mod n⇔k1n+i−k2n−j=aj−ai,
则(k1−k2)n=aj−ai+j−i=(aj+j)−(ai+i)(k_1-k_2)n=a_j-a_i+j-i=(a_j+j)-(a_i+i)(k1−k2)n=aj−ai+j−i=(aj+j)−(ai+i).
设bi=ai+ib_i=a_i+ibi=ai+i,则等价于求(k1−k2)n=cj−ci(k_1-k_2)n=c_j-c_i(k1−k2)n=cj−ci的正整数解ci,cjc_i,c_jci,cj,显然这等价于ci≡cj (mod n)c_i\equiv c_j\ \ (\mathrm{mod}\ n)ci≡cj (mod n).
预处理出所有(i+ai) mod n(i+a_i)\ \mathrm{mod}\ n(i+ai) mod n,检查余数是否为0∼(n−1)0\sim (n-1)0∼(n−1)即可.
代码
void solve() {
int n; cin >> n;
vi a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
a[i] = ((i + a[i]) % n + n) % n;
}
sort(all(a));
bool ok = true;
for (int i = 0; i < n; i++) ok &= a[i] == i;
cout << (ok ? "YES" : "NO") << endl;
}
int main() {
CaseT // 单测时注释掉该行
solve();
}