• [Codeforces] number theory (R1600) Part.10


    [Codeforces] number theory (R1600) Part.10

    题单:https://codeforces.com/problemset/page/1?tags=number+theory%2C1201-1600

    1423K. Lonely Numbers

    原题指路:https://codeforces.com/problemset/problem/1423/K

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

    称两个相异的正整数 a , b a,b a,b是朋友,如果 gcd ⁡ ( a , b ) , a gcd ⁡ ( a , b ) , b gcd ⁡ ( a , b ) \gcd(a,b),\dfrac{a}{\gcd(a,b)},\dfrac{b}{\gcd(a,b)} gcd(a,b),gcd(a,b)a,gcd(a,b)b可构成非退化三角形的边长.对一个由正整数构成的集合,称其中一个元素是孤独的,如果它在该集合中无朋友.给定由 [ 1 , n ] [1,n] [1,n]的整数组成的集合,求其中孤独的数的个数.

    t    ( 1 ≤ t ≤ 1 e 6 ) t\ \ (1\leq t\leq 1\mathrm{e}6) t  (1t1e6)组测试数据.每组测试数据输入一个整数 n    ( 1 ≤ n ≤ 1 e 6 ) n\ \ (1\leq n\leq 1\mathrm{e}6) n  (1n1e6).

    思路

    (1)素数 p p p非孤独当且仅当集合中存在 p 2 p^2 p2,此时组成三角形的三边分别为 p , 1 , p p,1,p p,1,p.

    (2)对合数 x = p 2    ( p ∈ p r i m e s ) x=p^2\ \ (p\in primes) x=p2  (pprimes),因 p 2 p^2 p2 [ 1 , n ] [1,n] [1,n]中,则 p p p也在 [ 1 , n ] [1,n] [1,n]中,故它不孤独.

    (3)对合数 x ≠ p 2    ( p ∈ p r i m e s ) x\neq p^2\ \ (p\in primes) x=p2  (pprimes),设组成三角形的三边分别为 a , b , c    ( a > c ) a,b,c\ \ (a>c) a,b,c  (a>c),其中 b = gcd ⁡ ( a , c ) ∈ ( 1 , a ) b=\gcd(a,c)\in \left(1,\sqrt{a}\right) b=gcd(a,c)(1,a ).

    ​ 下面证明 ∃ c ∈ Z   s . t .   a b + b > c b , a b + c b > b , c b + b > a b \exists c\in \mathbb{Z} \ s.t.\ \dfrac{a}{b}+b>\dfrac{c}{b},\dfrac{a}{b}+\dfrac{c}{b}>b,\dfrac{c}{b}+b>\dfrac{a}{b} cZ s.t. ba+b>bc,ba+bc>b,bc+b>ba.

    ​ ①因 a > c a>c a>c,则 a b + b > c b \dfrac{a}{b}+b>\dfrac{c}{b} ba+b>bc显然成立.

    ​ ②因 b < a b<\sqrt{a} b<a ,则 a b + c b > a b > b \dfrac{a}{b}+\dfrac{c}{b}>\dfrac{a}{b}>b ba+bc>ba>b.

    ​ ③下证 ∃ c ∈ Z   s . t .   a b − b < c < a b \exists c\in\mathbb{Z}\ s.t.\ \dfrac{a}{b}-bcZ s.t. bab<c<ba.因 b > 1 b>1 b>1,则区间长度 > 1 >1 >1,故区间内至少存在一个整数,故证.

    综上,一个数非孤独当且仅当它是素数且它的平方不在集合中.

    p r e [ i ] pre[i] pre[i] [ 1 , i ] [1,i] [1,i]中素数的个数,则 a n s = p r e [ n ] − p r e [ ⌊ n ⌋ ] + 1 ans=pre[n]-pre\left[\left\lfloor\sqrt{n}\right\rfloor\right] + 1 ans=pre[n]pre[n ]+1.

    代码

    const int MAXN = 1e6 + 5;
    int primes[MAXN], cnt;
    bool state[MAXN];
    int pre[MAXN];  // pre[i]表示[1,i]中素数的个数
    
    void init() {
      state[0] = state[1] = true;
    
      for (int i = 2; i < MAXN; i++) {
        if (!state[i]) primes[cnt++] = i;
    
        for (int j = 0; primes[j] * i < MAXN; j++) {
          state[primes[j] * i] = true;
          if (i % primes[j] == 0) break;
        }
      }
    
      for (int i = 1; i < MAXN; i++) pre[i] = pre[i - 1] + !state[i];
    }
    
    void solve() {
      int n; cin >> n;
      cout << pre[n] - pre[(uint)sqrt(n)] + 1 << endl;
    }
    
    int main() {
      init();
      CaseT  // 单测时注释掉该行
        solve();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30


    1444A. Division

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

    题意

    t    ( 1 ≤ t ≤ 50 ) t\ \ (1\leq t\leq50) t  (1t50)组测试数据.每组测试数据给定一对整数 p , q    ( 1 ≤ p ≤ 1 e 18 , 2 ≤ q ≤ 1 e 9 ) p,q\ \ (1\leq p\leq 1\mathrm{e}18,2\leq q\leq 1\mathrm{e}9) p,q  (1p1e18,2q1e9),求一个最大的 x   s . t .   x ∣ p , q ∤ x x\ s.t.\ x\mid p,q\not\mid x x s.t. xp,qx.

    思路

    x ∣ p x\mid p xp表示 x x x的所有素因子都在 p p p中出现, q ∤ x q\not\mid x qx表示 q q q存在 x x x没有的素因子或 q q q x x x中同一素因子的次数前者 > > >后者.

    x ∣ p x\mid p xp,则 x ≤ p x\leq p xp,而 q ≤ 1 e 9 q\leq 1\mathrm{e}9 q1e9,先将其素因数分解,对每个素因数 i i i,从 t m p = p tmp=p tmp=p开始一直除以 i i i直至 q ∤ t m p q\not\mid tmp qtmp,最终答案即 q q q的所有素因子得到的 t m p tmp tmp max ⁡ \max max.时间复杂度 O ( p + log ⁡ p ⋅ log ⁡ q ) O(\sqrt{p}+\log p\cdot \log q) O(p +logplogq).

    代码

    vi get(int n) {  // 求n的素因子
    	vi res;
    	for (int i = 2; i <= n / i; i++) {
    		if (n % i == 0) res.push_back(i);
    		while (n % i == 0) n /= i;
    	}
    	
    	if (n > 1) res.push_back(n);
    	return res;
    }
    
    void solve() {
    	ll p, q; cin >> p >> q;
    	if (p % q) {
    		cout << p << endl;
    		return;
    	}
    	
    	ll ans = 1;
    	for (auto i : get(q)) {
    		ll tmp = p;
    		while (tmp % q == 0) tmp /= i;
    		ans = max(ans, tmp);
    	}
    	cout << ans << endl;
    }
    
    int main() {
    	CaseT  // 单测时注释掉该行
    		solve();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31


    1454D. Number into Sequence

    原题指路:https://codeforces.com/problemset/problem/1454/D

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

    给定一个整数 n > 1 n>1 n>1,构造一个序列 a 1 , ⋯   , a k   s . t .   ∏ i = 1 k a i = n , a i ∣ a i + 1    ( 1 ≤ i ≤ k − 1 ) a_1,\cdots,a_k\ s.t.\ \displaystyle \prod_{i=1}^k a_i=n,a_i\mid a_{i+1}\ \ (1\leq i\leq k-1) a1,,ak s.t. i=1kai=n,aiai+1  (1ik1),且 k k k尽量大.若有多组解,输出任一组.

    t    ( 1 ≤ t ≤ 5000 ) t\ \ (1\leq t\leq 5000) t  (1t5000)组测试数据.每组测试数据输入一个整数 n    ( 2 ≤ n ≤ 1 e 10 ) n\ \ (2\leq n\leq 1\mathrm{e}10) n  (2n1e10).数据保证所有测试数据的 n n n之和不超过 1 e 10 1\mathrm{e}10 1e10.

    思路

    n = ∏ i = 1 m p i α i \displaystyle n=\prod_{i=1}^m p_i^{\alpha_i} n=i=1mpiαi,则 k ≤ min ⁡ 1 ≤ i ≤ m α i = a j \displaystyle k\leq \min_{1\leq i\leq m}\alpha_i=a_j k1imminαi=aj.取 a 1 = ⋯ = a k − 1 = p j , a k = n p j k − 1 a_1=\cdots=a_{k-1}=p_j,a_k=\dfrac{n}{p_j^{k-1}} a1==ak1=pj,ak=pjk1n即可.

    代码

    vll get(ll n) {  // 求n的素因数分解
      vll res;
      for (int i = 2; (ll)i * i <= n; i++) {
        if (n % i == 0) {
          int s = 0;
          while (n % i == 0) n /= i, s++;
          res.push_back({ s,i });
        }
      }
      if (n > 1) res.push_back({ 1,n });
      return res;
    }
    
    void solve() {
      ll n; cin >> n;
    
      auto factors = get(n);
      sort(all(factors), greater());
    
      vl ans(factors[0].first, factors[0].second);
      for (int i = 1; i < factors.size(); i++)
        ans.back() *= pow(factors[i].second, factors[i].first);
    
      cout << ans.size() << endl;
      for (auto i : ans) cout << i << ' ';
      cout << endl;
    }
    
    int main() {
      CaseT  // 单测时注释掉该行
        solve();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32


    1458A. Row GCD

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

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

    给定一个长度为 n    ( 1 ≤ n ≤ 2 e 5 ) n\ \ (1\leq n\leq 2\mathrm{e}5) n  (1n2e5)的序列 a 1 , ⋯   , a n    ( 1 ≤ a i ≤ 1 e 18 ) a_1,\cdots,a_n\ \ (1\leq a_i\leq 1\mathrm{e}18) a1,,an  (1ai1e18)和一个长度为 m    ( 1 ≤ m ≤ 2 e 5 ) m\ \ (1\leq m\leq 2\mathrm{e}5) m  (1m2e5)的序列 b 1 , ⋯   , b m    ( 1 ≤ b i ≤ 1 e 18 ) b_1,\cdots,b_m\ \ (1\leq b_i\leq 1\mathrm{e}18) b1,,bm  (1bi1e18).对每个 j ∈ [ 1 , m ] j\in[1,m] j[1,m],求 gcd ⁡ ( a 1 + b j , ⋯   , a n + b j ) \gcd(a_1+b_j,\cdots,a_n+b_j) gcd(a1+bj,,an+bj).

    思路

    注意到 gcd ⁡ ( a 1 + b j , ⋯   , a n + b j ) = gcd ⁡ ( a 1 + b j , a 2 − a 1 , ⋯   , a n − a 1 ) \gcd(a_1+b_j,\cdots,a_n+b_j)=\gcd(a_1+b_j,a_2-a_1,\cdots,a_n-a_1) gcd(a1+bj,,an+bj)=gcd(a1+bj,a2a1,,ana1)即可.

    代码

    void solve() {
      int n, m; cin >> n >> m;
      vl a(n), b(m);
      for (auto& ai : a) cin >> ai;
      for (auto& bi : b) cin >> bi;
    
      ll g = 0;
      for (int i = 1; i < n; i++) g = gcd(g, abs(a[i] - a[i - 1]));
    
      for (int i = 0; i < m; i++) cout << gcd(g, a[0] + b[i]) << ' ';
    }
    
    int main() {
      solve();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15


    1462D. Add to Neighbour and Remove

    原题指路:https://codeforces.com/problemset/problem/1462/D

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

    给定一个长度为 n n n的序列 a 1 , ⋯   , a n a_1,\cdots,a_n a1,,an.现有操作,每次操作分为两步:①选择一个下标 a i a_i ai,令 a i − 1 + = a i a_{i-1}+=a_i ai1+=ai a i + 1 + = a i a_{i+1}+=a_i ai+1+=ai;②移除 a i a_i ai.问至多 n n n次操作后能否使得 a [ ] a[] a[]中的元素都相等.

    t    ( 1 ≤ t ≤ 3000 ) t\ \ (1\leq t\leq 3000) t  (1t3000)组测试数据.每组测试数据第一行输入一个整数 n    ( 1 ≤ n ≤ 3000 ) n\ \ (1\leq n\leq 3000) n  (1n3000).第二行输入 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之和不超过 3000 3000 3000.

    思路

    因序列至多操作 ( n − 1 ) (n-1) (n1)次,可枚举操作次数 i i i,则操作后剩下 ( n − i ) (n-i) (ni)个元素.

    注意到每次操作后序列的元素之和 s u m sum sum不变,若最后所有元素等于 k k k,则 s u m = ( n − i ) k sum=(n-i)k sum=(ni)k.模拟操作过程,检查答案是否合法即可,时间复杂度 O ( n 2 ) O(n^2) O(n2).

    代码

    const int MAXN = 3005;
    int n;
    int a[MAXN];
    
    bool check(int m, int k) {  // 判断操作后能否剩下m个k
      int sum = 0, cnt = 0;  // 当前数之和、
      for (int i = 0; i < n; i++) {
        sum += a[i];
        if (sum > k) return false;  //  不合法
        if (sum == k) cnt++, sum = 0;  // 凑出一个k
      }
      return cnt == m;
    }
    
    void solve() {
      cin >> n;
      int sum = 0;
      for (int i = 0; i < n; i++) {
        cin >> a[i];
        sum += a[i];
      }
    
      for (int i = 0; i < n; i++) {  // 枚举操作次数
        if (sum % (n - i) == 0 && check(n - i, sum / (n - i))) {
          cout << i << endl;
          return;
        }
      }
    }
    
    int main() {
      CaseT  // 单测时注释掉该行
        solve();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34


    1487D. Pythagorean Triples

    原题指路:https://codeforces.com/problemset/problem/1487/D

    题意 ( 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).求有多少个整数三元组 ( a , b , c )   s . t .   1 ≤ a ≤ b ≤ c ≤ n (a,b,c)\ s.t.\ 1\leq a\leq b\leq c\leq n (a,b,c) s.t. 1abcn,且 a 2 + b 2 = c 2 , c = a 2 − b a^2+b^2=c^2,c=a^2-b a2+b2=c2,c=a2b.

    思路

    c 2 = a 2 + b 2 , c = a 2 − b c^2=a^2+b^2,c=a^2-b c2=a2+b2,c=a2b,两式相减得 b 2 + b = c 2 − c b^2+b=c^2-c b2+b=c2c,即 b ( b + 1 ) = c ( c − 1 ) b(b+1)=c(c-1) b(b+1)=c(c1),则 c = b + 1 c=b+1 c=b+1.

    代入得 a 2 = 2 b + 1 a^2=2b+1 a2=2b+1,即每个 > 1 >1 >1的奇数 a a a对应唯一的一个 b b b,进而对应唯一的一个 c c c.枚举奇数 a a a,检查对应的 c c c是否不超过 n n n即可,时间复杂度 O ( a ) ≈ O ( c ) = O ( n ) O(a)\approx O\left(\sqrt{c}\right)=O\left(\sqrt{n}\right) O(a)O(c )=O(n ).

    代码

    void solve() {
      int n; cin >> n;
    
      int ans = 0;
      for (int i = 3; (ll)i * i <= 2 * n - 1; i += 2) ans++;
      cout << ans << endl;
    }
    
    int main() {
      CaseT  // 单测时注释掉该行
        solve();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12


    1505B. DMCA

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

    题意

    给定一个整数 n    ( 1 ≤ n ≤ 1 e 6 ) n\ \ (1\leq n\leq 1\mathrm{e}6) n  (1n1e6),求其digit root.

    思路

    d = n   m o d   9 d=n\ \mathrm{mod}\ 9 d=n mod 9,则 n n n的digit root为 { d , d ≠ 0 9 , d = 0 {d,d09,d=0 {d,d=09,d=0.

    代码

    void solve() {
      int n; cin >> n;
      cout << (n % 9 ? n % 9 : 9);
    }
    
    int main() {
      solve();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8


    1514C. Product 1 Modulo N

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

    题意

    给定一个整数 n    ( 2 ≤ n ≤ 1 e 5 ) n\ \ (2\leq n\leq 1\mathrm{e}5) n  (2n1e5),在序列 [ 1 , ⋯   , n − 1 ] [1,\cdots,n-1] [1,,n1]中求一个最长的子列使得其中元素之积模 n n n 1 1 1,升序输出该子列.

    思路

    乘积模 n n n 1 1 1,则乘积可表示为一个数乘它模 n n n意义下的逆元.显然不能选模 n n n意义下逆元不存在或逆元不在集合中的数,而 a a a在模 n n n意义下不存在逆元当且仅当 gcd ⁡ ( a , n ) ≠ 1 \gcd(a,n)\neq 1 gcd(a,n)=1,故不能选与 n n n不互素的数.

    设所有与 n n n互素的数之积在模 n n n下为 p r o d prod prod.

    ①若 p r o d = 1 prod=1 prod=1,则这些数全选即最优解.

    ②若 p r o d ≠ 1 prod\neq 1 prod=1,因 gcd ⁡ ( p r o d , n ) = 1 \gcd(prod,n)=1 gcd(prod,n)=1,不选值为 p r o d prod prod的数即可使得乘积在模 n n n下为 1 1 1.

    代码

    const int MAXN = 1e5 + 5;
    int n;
    bool ok[MAXN];  // 记录要选的数
    
    void solve() {
      cin >> n;
      int prod = 1;
      for (int i = 1; i < n; i++) {
        if (gcd(i, n) == 1) {
          ok[i] = true;
          prod = (ll)prod * i % n;
        }
      }
    
      if (prod != 1) ok[prod] = false;
    
      cout << count(ok + 1, ok + n + 1, 1) << endl;
      for (int i = 1; i < n; i++)
        if (ok[i]) cout << i << ' ';
    }
    
    int main() {
      solve();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24


    1519C. Berland Regional

    原题指路:https://codeforces.com/problemset/problem/1519/C

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

    有编号 1 ∼ n 1\sim n 1n n n n所大学.有编号 1 ∼ n 1\sim n 1n n n n个学生,其中 i i i号学生在 u i u_i ui号大学,其能力值为 s i s_i si.现设定队伍的人数 k k k,每个学校将选出能力前 k k k大的人组成一支队伍,该学校的能力值为其队伍成员的能力值之和.若某学校人数不足以组成队伍,则其能力值为 0 0 0.对每个 k ∈ [ 1 , n ] k\in [1,n] k[1,n],求所有大学的能力值之和.

    t    ( 1 ≤ t ≤ 1000 ) t\ \ (1\leq t\leq 1000) t  (1t1000)组测试数据.每组测试数据第一行输入一个整数 n    ( 1 ≤ n ≤ 2 e 5 ) n\ \ (1\leq n\leq 2\mathrm{e}5) n  (1n2e5).第二行输入 n n n个整数 u 1 , ⋯   , u n    ( 1 ≤ u i ≤ n ) u_1,\cdots,u_n\ \ (1\leq u_i\leq n) u1,,un  (1uin).第三行输入 n n n个整数 s 1 , ⋯   , s n    ( 1 ≤ s i ≤ 1 e 9 ) s_1,\cdots,s_n\ \ (1\leq s_i\leq 1\mathrm{e}9) s1,,sn  (1si1e9).数据保证所有测试数据的 n n n之和不超过 2 e 5 2\mathrm{e}5 2e5.

    思路

    将每个学校的学生按能力值降序排序,维护前缀和数组 p r e [ i ] [ j ] pre[i][j] pre[i][j]表示 i i i号学校的前 j j j个人的能力值之和.

    i i i号学校人数为 x i x_i xi,则其对答案的贡献为 p r e [ i ] [ ⌊ x i k ⌋ ⋅ k ] pre[i]\left[\left\lfloor\dfrac{x_i}{k}\right\rfloor\cdot k\right] pre[i][kxik],其中只有 k ∈ [ 1 , x i ] k\in [1,x_i] k[1,xi]需计算.

    代码

    void solve() {
      int n; cin >> n;
      vi u(n), s(n);
      for (auto& ui : u) {
        cin >> ui;
        ui--;
      }
      for (auto& si : s) cin >> si;
    
      vector school(n);
      for (int i = 0; i < n; i++) school[u[i]].push_back(s[i]);
    
      for (int i = 0; i < n; i++) sort(all(school[i]), greater());
    
      vector pre(n, vl(1, 0));  // pre[i][j]表示i号学校前j个同学的能力值之和
      for (int i = 0; i < n; i++) 
        for (auto j : school[i]) pre[i].push_back(pre[i].back() + j);
    
      vl ans(n + 1);
      for (int i = 0; i < n; i++) {
        for (int k = 1; k <= school[i].size(); k++)
          ans[k] += pre[i][school[i].size() / k * k];
      }
    
      for (int i = 1; i <= n; i++) cout << ans[i] << " \n"[i == n];
    }
    
    int main() {
      CaseT  // 单测时注释掉该行
        solve();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31


    1521B. Nastia and a Good Array

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

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

    称一个序列是好的,如果任意两相邻元素的 gcd ⁡ = 1 \gcd=1 gcd=1.给定一个长度为 n n n的序列 a 1 , ⋯   , a n a_1,\cdots,a_n a1,,an.现有操作:选择两不同的下标 i , j    ( 1 ≤ i , j ≤ n , i ≠ j ) i,j\ \ (1\leq i,j\leq n,i\neq j) i,j  (1i,jn,i=j)和两个整数 x , y   s . t .   min ⁡ { a i , a j } = min ⁡ { x , y } x,y\ s.t.\ \min\{a_i,a_j\}=\min\{x,y\} x,y s.t. min{ai,aj}=min{x,y},令 a i = x , a j = y a_i=x,a_j=y ai=x,aj=y.用至多 n n n次操作将序列变为好的序列,可以证明一定有解.

    t    ( 1 ≤ t ≤ 1 e 4 ) t\ \ (1\leq t\leq 1\mathrm{e}4) t  (1t1e4)组测试数据.每组测试数据第一行输入一个整数 n    ( 1 ≤ n ≤ 1 e 5 ) n\ \ (1\leq n\leq 1\mathrm{e}5) n  (1n1e5).第二行输入 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  (1ai1e9).数据保证所有测试数据的 n n n之和不超过 2 e 5 2\mathrm{e}5 2e5.

    思路

    x = min ⁡ 1 ≤ i ≤ n a i = a p o s \displaystyle x=\min_{1\leq i\leq n}a_i=a_{pos} x=1inminai=apos.考虑构造一个以 a p o s a_pos apos为谷底的"V字型",使得任意两相邻元素相差 1 1 1.

    对每个下标 i    ( 1 ≤ i ≤ n , i ≠ p o s ) i\ \ (1\leq i\leq n,i\neq pos) i  (1in,i=pos),做操作 ( p o s , i , x , x + ∣ p o s − i ∣ ) (pos,i,x,x+|pos-i|) (pos,i,x,x+posi),显然它符合 min ⁡ { a i , a j } = min ⁡ { x , y } \min\{a_i,a_j\}=\min\{x,y\} min{ai,aj}=min{x,y},其效果为令 a i = x + ∣ p o s − i ∣ a_i=x+|pos-i| ai=x+posi.

    代码

    void solve() {
      int n; cin >> n;
      int x = INF, pos = 0;
      for (int i = 1; i <= n; i++) {
        int a; cin >> a;
        if (a < x) x = a, pos = i;
      }
    
      cout << (n - 1) << endl;
      for (int i = 1; i <= n; i++) {
        if (i != pos) 
          cout << pos << ' ' << i << ' ' << x << ' ' << x + abs(pos - i) << endl;
      }
    }
    
    int main() {
      CaseT  // 单测时注释掉该行
        solve();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19


  • 相关阅读:
    做大模型产品,如何设计prompt?
    解决ubuntu终端能不能正常显示中文
    Qt——设置布局中特定的两个组件之间的间距
    SQALE 是什么
    R语言ggplot2可视化:可视化多行文本内容并添加箭头和文本框、指定文本可视化内容右对齐(right alignment)
    Java基础面试-JDK JRE JVM
    Qt学习03 Qt的诞生和本质
    [Python进阶] 获取计算机相关信息:WMI
    wpf 自定义命令
    【财务系统】报告如何转换下载为word?这个方法值得借鉴
  • 原文地址:https://blog.csdn.net/Hytidel/article/details/127134906