[Codeforces] number theory (R1200) Part.8

[Codeforces] number theory (R1200) Part.8

题单:https://codeforces.com/problemset/page/6?tags=number%20theory,0-1200

1511B. GCD Length

原题指路:https://codeforces.com/problemset/problem/1511/B

题意 ( 2   s 2\ \mathrm{s} 2 s)

给定三个整数 a , b , c a,b,c a,b,c,构造任两个正整数 x , y   s . t .   x x,y\ s.t.\ x x,y s.t. x的十进制表示(不含前导零,下同)包含 a a a个数码, y y y的十进制表示包含 b b b个数码, gcd ⁡ ( x , y ) \gcd(x,y) gcd(x,y)的十进制表示包含 c c c个数码.

t    ( 1 ≤ t ≤ 285 ) t\ \ (1\leq t\leq 285) t  (1t285)组测试数据.每组测试数据输入三个整数 a , b , c    ( 1 ≤ a , b ≤ 9 , 1 ≤ c ≤ min ⁡ { a , b } ) a,b,c\ \ (1\leq a,b\leq 9,1\leq c\leq \min\{a,b\}) a,b,c  (1a,b9,1cmin{a,b}).数据保证有解.

思路

x = 1 0 ⋯ 0 ⏟ ( a − c ) 个 0 ⋯ 0 ⏟ ( c − 1 ) 个 , y = 1 1 ⋯ 1 ⏟ ( b − c ) 个 0 ⋯ 0 ⏟ ( c − 1 ) 个 x=1\underbrace{0\cdots 0}_{(a-c)个}\underbrace{0\cdots 0}_{(c-1)个},y=1\underbrace{1\cdots 1}_{(b-c)个}\underbrace{0\cdots 0}_{(c-1)个} x=1(ac) 00(c1) 00,y=1(bc) 11(c1) 00.因 gcd ⁡ ( 10 ⋯ 0 , 11 ⋯ 1 ) = 1 \gcd(10\cdots 0,11\cdots 1)=1 gcd(100,111)=1,故满足条件.

代码

void solve() {
	int a, b, c; cin >> a >> b >> c;
    cout << "1" << string(a - 1, '0') << ' ' << string(b - c + 1, '1') << string(c - 1, '0') << endl;
} 

int main() {
	CaseT  // 单测时注释掉该行
	solve();
}


1514A. Perfectly Imperfect Array

原题指路:https://codeforces.com/problemset/problem/1514/A

题意

称一个序列是好的,如果它存在一个非空的子列使得其中元素之积不是完全平方数.

t    ( 1 ≤ t ≤ 100 ) t\ \ (1\leq t\leq 100) t  (1t100)组测试数据.每组测试数据第一行输入一个整数 n    ( 1 ≤ n ≤ 100 ) n\ \ (1\leq n\leq 100) n  (1n100),表示序列长度.第二行输入 n n n个整数 a 1 , ⋯   , a n    ( 1 ≤ a i ≤ 1 e 4 ) a_1,\cdots,a_n\ \ (1\leq a_i\leq 1\mathrm{e}4) a1,,an  (1ai1e4).

对每组测试数据,若序列 a [ ] a[] a[]是好的,输出"YES";否则输出"NO".

思路

注意到若序列 a [ ] a[] a[]中包含一个非完全平方数,则它是好的.

代码

bool check(int x) {
    int tmp = sqrt(x);
    return x == tmp * tmp;
}

void solve() {
	int n; cin >> n;

    bool ok = false;
    while (n--) {
        int x; cin >> x;
        ok |= !check(x);
    }
    cout << (ok ? "YES" : "NO") << endl;
} 

int main() {
	CaseT  // 单测时注释掉该行
	solve();
}


1515B. Phoenix and Puzzle

原题指路:https://codeforces.com/problemset/problem/1515/B

题意 ( 2   s 2\ \mathrm{s} 2 s)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

n n n个如图(1)所示的等腰直角三角形的拼图,问能否用它们拼成一个正方形,使得所有的拼图都用完,若能则输出"YES";否则输出"NO".

t    ( 1 ≤ t ≤ 1 e 4 ) t\ \ (1\leq t\leq 1\mathrm{e}4) t  (1t1e4)组测试数据.每组测试数据输入一个整数 n    ( 1 ≤ n ≤ 1 e 9 ) n\ \ (1\leq n\leq 1\mathrm{e}9) n  (1n1e9).

思路

如图(2)和图(3)所示,可用 2 2 2块或 4 4 4块拼图拼成一个小正方形.设小正方形的数量为 x x x,则用小正方先能拼成一个大正方形的充要条件是: x x x是完全平方数.

有解的条件只能是下列两条件之一:① n n n 2 2 2的倍数,且 n 2 \dfrac{n}{2} 2n是完全平方数;② n n n 4 4 4的倍数,且 n 4 \dfrac{n}{4} 4n是完全平方数.

[] 下面证明无其他解.设直角三角形的直角边长为 1 1 1,则斜边长为 2 \sqrt{2} 2 .

设拼成的大正方形的边长用到了 a a a条直角边和 b b b条斜边,则其边长为 a + 2 b a+\sqrt{2}b a+2 b.

注意到大正方形的面积 ( a + 2 b ) 2 \left(a+\sqrt{2}b\right)^2 (a+2 b)2是有理数,则 a = 0 a=0 a=0 b = 0 b=0 b=0.

代码

bool check(int x) {
    int tmp = sqrt(x);
    return x == tmp * tmp;
}

void solve() {
	int n; cin >> n;

    bool ok = false;
    ok |= n % 2 == 0 && check(n / 2);
    ok |= n % 4 == 0 && check(n / 4);
    cout << (ok ? "YES" : "NO") << endl;
} 

int main() {
	CaseT  // 单测时注释掉该行
	solve();
}


1520B. Ordinary Numbers

原题指路:https://codeforces.com/problemset/problem/1520/B

题意 ( 2   s 2\ \mathrm{s} 2 s)

称一个整数是好的,如果它的所有数码都相同.

t    ( 1 ≤ t ≤ 1 e 4 ) t\ \ (1\leq t\leq 1\mathrm{e}4) t  (1t1e4)组测试数据.每组测试数据输入一个整数 n    ( 1 ≤ n ≤ 1 e 9 ) n\ \ (1\leq n\leq 1\mathrm{e}9) n  (1n1e9),问 [ 1 , n ] [1,n] [1,n]中好的数的个数.

思路

注意到好的数可表示为 d ( 1 0 0 + 1 0 1 + ⋯ + 1 0 k ) d(10^0+10^1+\cdots+10^k) d(100+101++10k),则只需统计   s . t .   d ( 1 0 0 + 1 0 1 + ⋯ + 1 0 k ) ≤ n \ s.t.\ d(10^0+10^1+\cdots+10^k)\leq n  s.t. d(100+101++10k)n的整数对 ( d , k ) (d,k) (d,k)的个数,其中 d ∈ [ 1 , 9 ] , k ∈ [ 0 , 8 ] d\in[1,9],k\in[0,8] d[1,9],k[0,8],暴力统计即可.

代码

void solve() {
	int n; cin >> n;
    
    int ans = 0;
    for (ll pow10 = 1; pow10 <= n; pow10 = pow10 * 10 + 1) {
        for (int d = 1; d <= 9; d++) 
            ans += pow10 * d <= n;
    }
    cout << ans << endl;
}

int main() {
	CaseT  // 单测时注释掉该行
	solve();
}


1521A. Nastia and Nearly Good Numbers

原题指路:https://codeforces.com/problemset/problem/1521/A

题意

给定两整数 A , B A,B A,B,①称一个整数是好的,如果它能被 A B AB AB整除;②称一个整数是近似好的,如果它能被 A A A整除.构造三个相异的正整数 x , y , z x,y,z x,y,z,使得其中恰有一个好的数、恰有两个近似好的数,且 x + y = z x+y=z x+y=z.

t    ( 1 ≤ t ≤ 1 e 4 ) t\ \ (1\leq t\leq 1\mathrm{e}4) t  (1t1e4)组测试数据.每组测试数据输入两个整数 A , B    ( 1 ≤ A , B ≤ 1 e 6 ) A,B\ \ (1\leq A,B\leq 1\mathrm{e}6) A,B  (1A,B1e6).

对每组测试数据,若有解,输出"YES"并输出满足条件的三个整数 x , y , z    ( 1 ≤ x , y , z ≤ 1 e 18 ) x,y,z\ \ (1\leq x,y,z\leq 1\mathrm{e}18) x,y,z  (1x,y,z1e18);否则输出"NO".

思路

B = 1 B=1 B=1时,被 A B AB AB整除即被 A A A整除,此时好的和近似好的等价,无解.

B ≥ 2 B\geq 2 B2时,取 A + A B = A ( B + 1 ) A+AB=A(B+1) A+AB=A(B+1).

代码

void solve() {
	int a, b; cin >> a >> b;

    if (b == 1) cout << "NO" << endl;
    else {
        cout << "YES" << endl;
        cout << a << ' ' << (ll)a * b <<' ' << (ll)a * (b + 1) << endl;
    }
}

int main() {
	CaseT  // 单测时注释掉该行
	solve();
}


1525A. Potion-making

原题指路:https://codeforces.com/problemset/problem/1525/A

题意

有A和B两种水,现要配置包含 k % k\% k%的A水和 ( 100 − k ) % (100-k)\% (100k)%的B水的水,每次操作可加 1 1 1单位的A水或B水,问最少操作次数.

t    ( 1 ≤ t ≤ 100 ) t\ \ (1\leq t\leq 100) t  (1t100)组测试数据.每组测试数据输入一个整数 k    ( 1 ≤ k ≤ 100 ) k\ \ (1\leq k\leq 100) k  (1k100).

思路

首先必有解,最坏可加 k k k次A水和 ( 100 − k ) (100-k) (100k)次B水.

设A水、B水分别加 x x x y y y次,则 x x + y = k 100 \dfrac{x}{x+y}=\dfrac{k}{100} x+yx=100k.显然 ( x + y ) ∣ 100 (x+y)\mid 100 (x+y)100,不妨设 z ( x + y ) = 100 z(x+y)=100 z(x+y)=100,则 z x = k zx=k zx=k,即 x = k z x=\dfrac{k}{z} x=zk.

代入 z ( x + y ) = 100 z(x+y)=100 z(x+y)=100,解得 y = 100 − k z y=\dfrac{100-k}{z} y=z100k,则 a n s = x + y = 100 z ans=x+y=\dfrac{100}{z} ans=x+y=z100.

x , a n s ∈ Z x,ans\in\mathbb{Z} x,ansZ,则 z ∣ k , z ∣ 100 z\mid k,z\mid 100 zk,z100.为使得 a n s ans ans最小,取 z = gcd ⁡ ( 100 , k ) z=\gcd(100,k) z=gcd(100,k).

代码

void solve() {
	int k; cin >> k;
    cout << 100 / gcd(100, k) << endl;
}

int main() {
	CaseT  // 单测时注释掉该行
	solve();
}


1535B. Array Reodering

原题指路:https://codeforces.com/problemset/problem/1535/B

题意

对序列 a 1 , ⋯   , a n a_1,\cdots,a_n a1,,an称一对下标 ( i , j )    ( 1 ≤ i < j ≤ n ) (i,j)\ \ (1\leq i<j\leq n) (i,j)  (1i<jn)是好的,如果 gcd ⁡ ( a i , 2 a j ) > 1 \gcd(a_i,2a_j)>1 gcd(ai,2aj)>1.将 a [ ] a[] a[]排序,使得其好的下标的对数最多,输出好的下标的对数.

t    ( 1 ≤ t ≤ 1000 ) t\ \ (1\leq t\leq 1000) t  (1t1000)组测试数据.每组测试数据第一行输入一个整数 n    ( 2 ≤ n ≤ 2000 ) n\ \ (2\leq n\leq 2000) n  (2n2000).第二行输入 n n n个整数 a 1 , ⋯   , a n    ( 1 ≤ a i ≤ 1 e 5 ) a_1,\cdots,a_n\ \ (1\leq a_i\leq 1\mathrm{e}5) a1,,an  (1ai1e5).数据保证所有测试数据的 n n n之和不超过 2000 2000 2000.

思路

显然应将偶数排在前面,奇数排在后面.显然偶数间顺序无关.对奇数 a i , a j , gcd ⁡ ( a i , 2 a j ) = gcd ⁡ ( a i , a j ) a_i,a_j,\gcd(a_i,2a_j)=\gcd(a_i,a_j) ai,aj,gcd(ai,2aj)=gcd(ai,aj),故奇数间的顺序无关.

代码

void solve() {
	int n; cin >> n;
	vi a(n);
	for (int& ai : a) cin >> ai;

	sort(all(a), [&](const int& A, const int& B) {
		return A % 2 < B % 2;
		});

	int ans = 0;
	for (int i = 0; i < n; i++) {
		for (int j = i + 1; j < n; j++)
			ans += gcd(a[i], a[j] * 2) > 1;
	}
	cout << ans << endl;
}

int main() {
	CaseT  // 单测时注释掉该行
	solve();
}


1541B. Pleasant Pairs

原题指路:https://codeforces.com/problemset/problem/1541/B

题意

给定一个包含 n n n个相异整数的序列 a 1 , ⋯   , a n a_1,\cdots,a_n a1,,an,求使得 1 ≤ i < j ≤ n 1\leq i<j\leq n 1i<jn a i ⋅ a j = i + j a_i\cdot a_j=i+j aiaj=i+j的整数对 ( i , j ) (i,j) (i,j)的对数.

t    ( 1 ≤ t ≤ 1 e 4 ) t\ \ (1\leq t\leq 1\mathrm{e}4) t  (1t1e4)组测试数据.每组测试数据第一行输入一个整数 n    ( 2 ≤ n ≤ 1 e 5 ) n\ \ (2\leq n\leq 1\mathrm{e}5) n  (2n1e5).第二行输入 n n n个相异的整数 a 1 , ⋯   , a n    ( 1 ≤ a i ≤ 2 n ) a_1,\cdots,a_n\ \ (1\leq a_i\leq 2n) a1,,an  (1ai2n).数据保证所有测试数据的 n n n之和不超过 2 e 5 2\mathrm{e}5 2e5.

思路

注意到 a i ⋅ a j = i + j ≤ 2 n a_i\cdot a _j=i+j\leq 2n aiaj=i+j2n,可枚举每个 ( i + j ) (i+j) (i+j)的值后再枚举每个 a i a_i ai,检查是否存在满足条件的元素即可.

满足上述条件的整数对 ( i , j ) (i,j) (i,j) O ( n log ⁡ n ) O(n\log n) O(nlogn)对.

[] 设 a i = x a_i=x ai=x,则 a j a_j aj至多有 2 n x \dfrac{2n}{x} x2n种取值. ∑ i = 1 n 2 n i = 2 n ∑ i = 1 n 1 i = O ( n log ⁡ n ) \displaystyle\sum_{i=1}^n \dfrac{2n}{i}=2n\sum_{i=1}^n \dfrac{1}{i}=O(n\log n) i=1ni2n=2ni=1ni1=O(nlogn).

代码

void solve() {
	int n; cin >> n;
  umap<int, int> pos;  // 每个a_i的值所在的下标
  for (int i = 1; i <= n; i++) {
    int a; cin >> a;
    pos[a] = i;
  }

  int ans = 0;
  for (int i = 2; i <= 2 * n; i++) {  // 枚举i+j
    for (int j = 1; j * j < i; j++) {  // 枚举a[i],注意不是<=
      if (i % j ==  0) {
        int k = i / j;
        if (pos[j] && pos[k] && pos[j] + pos[k] == i) ans++;
      }
    }
  }
  cout << ans << endl;
} 

int main() {
	CaseT  // 单测时注释掉该行
	solve();
}


1543A. Exciting Bets

原题指路:https://codeforces.com/problemset/problem/1543/A

题意

给定两正整数 a , b a,b a,b.现有两种操作:① a + + , b + + a++,b++ a++,b++;② a − − , b − − a--,b-- a,b,此操作当且仅当 a , b > 0 a,b>0 a,b>0时可执行.问经过若干次(可能为零次)操作后 gcd ⁡ ( a , b ) \gcd(a,b) gcd(a,b)的最大值.

t    ( 1 ≤ t ≤ 5000 ) t\ \ (1\leq t\leq 5000) t  (1t5000)组测试数据.每组测试数据输入两个整数 a , b    ( 0 ≤ a , b ≤ 1 e 18 ) a,b\ \ (0\leq a,b\leq 1\mathrm{e}18) a,b  (0a,b1e18).

对每组测试数据,若 gcd ⁡ ( a , b ) \gcd(a,b) gcd(a,b)可达到无穷大,则输出"0 0";否则先输出 gcd ⁡ ( a , b ) \gcd(a,b) gcd(a,b)的最大值,再输出达到最大值所需的最小步数.

思路

a = b a=b a=b时,一直做操作①即可使得 gcd ⁡ ( a , b ) = I N F \gcd(a,b)=INF gcd(a,b)=INF.

②不妨设 a ≥ b a\geq b ab. gcd ⁡ ( a , b ) \gcd(a,b) gcd(a,b)能取得的最大值是 a − b a-b ab.

​ [] 注意到 gcd ⁡ ( a , b ) = gcd ⁡ ( a − b , b ) \gcd(a,b)=\gcd(a-b,b) gcd(a,b)=gcd(ab,b),其中 g = a − b g=a-b g=ab在操作过程中不变,

​ 为使得 gcd ⁡ ( a , b ) \gcd(a,b) gcd(a,b)最大,应通过操作将 b b b变为 g g g的倍数.

≤ b \leq b b的最大的 g g g的倍数是 ⌊ b g ⌋ ⋅ g \left\lfloor\dfrac{b}{g}\right\rfloor \cdot g gbg,则将 b b b减至该倍数所需步数为 b − ⌊ b g ⌋ ⋅ g = b % g b-\left\lfloor\dfrac{b}{g}\right\rfloor \cdot g=b\%g bgbg=b%g.

​ 显然将 b b b加至 ≥ b \geq b b的最小的 g g g的倍数所需步数为 g − b % g g-b\% g gb%g.

代码

void solve() {
	ll a, b; cin >> a >> b;
    
  if (a == b) cout << "0 0" << endl;
  else {
    if (b > a) swap(a, b);

    ll g = a - b;
    cout << g << ' ' << min(b % g, g - b % g) << endl;
  }
} 

int main() {
	CaseT  // 单测时注释掉该行
	solve();
}


1549A. Gregor and Cryptography

原题指路:https://codeforces.com/problemset/problem/1549/A

题意

给定一个素数 p p p,求两个整数 a , b   s . t .   2 ≤ a < b ≤ p , p % a = p % b a,b\ s.t.\ 2\leq a<b\leq p,p\%a=p\%b a,b s.t. 2a<bp,p%a=p%b.

t    ( 1 ≤ t ≤ 1000 ) t\ \ (1\leq t\leq 1000) t  (1t1000)组测试数据.每组测试数据输入一个素数 p    ( 5 ≤ p ≤ 1 e 9 ) p\ \ (5\leq p\leq 1\mathrm{e}9) p  (5p1e9).

思路

因素数 p ≥ 5 p\geq 5 p5,则 p p p是奇数,进而 ( p − 1 ) (p-1) (p1)是偶数.取 a = 2 , b = p − 1 a=2,b=p-1 a=2,b=p1即可.

代码

void solve() {
	int n; cin >> n;
  cout << 2 << ' ' << n - 1 << endl;
}

int main() {
	CaseT  // 单测时注释掉该行
	solve();
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值