codeforces 798C.Mike and gcd problem 解题报告

题目意思:给出一个n个数序列:a1,a2,...,an (n的范围[2,100000],ax的范围[1,1e9]

然后想构造一个beautiful的序列 b1,b2, ..., bn,使得最大公约数 gcd(b1,b2,...,bn) > 1。任意ai,ai+1 可以用 ai-ai+1, ai+ai+1 来替换。

问序列 a 构造成 b 的最小操作次数

  首先,这个题目是肯定有解的,也就是恒输出yes

试想一下,相邻两个数之间无非就是四种情况:

(1)对于同偶情况,不需要做转换,公约数直接为2;

(2)对于同奇情况,只需要变换一次,两奇数进行加减操作,最终结果是偶数,公约数此时为2

  (3)一奇一偶,变换两次: ai, ai+1 ——》 ai-ai+1, ai+ai+1  ——》2(ai+1,ai) ——》 公约数为2

  此时问题就变成: 构造一个所有序列的公约数为2的最少操作次数。

当然,在处理序列之前,先判断整个序列是不是已经有公约数了(注意,并不一定为2)

两种方法

方法一 :常规贪心+数论

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 using namespace std;
 6
 7 const int maxn = 1e5 + 5;
 8 int a[maxn];
 9
10 int GCD(int b1, int b2)
11 {
12     if (b2 == 0)
13         return b1;
14     return GCD(b2, b1%b2);
15 }
16
17 int main()
18 {
19     #ifndef ONLINE_JUDGE
20         freopen("in.txt", "r", stdin);
21     #endif // ONLINE_JUDGE
22
23     int n;
24     while (scanf("%d", &n) !=EOF) {
25        scanf("%d", &a[0]);
26        int t=a[0], cnt = 0;
27        for (int i = 1; i < n; i++) {
28         scanf("%d", &a[i]);
29         t = GCD(t, a[i]);
30         if (t > 1) { cnt++; }
31        }
32        printf("YES\n");
33        if ( cnt == n-1 ) { printf("0\n"); }  // all is even
34        else {
35             // scan two times;
36             int ans = 0;
37             for (int i = 0; i < n; i++) {
38                 if (a[i]%2 && a[i+1]%2 && i+1 < n) {  // two odd
39                     ans += 1;
40                     a[i] = 2;
41                     a[i+1] = 2;
42                 }
43             }
44
45             for (int i = 0; i < n; i++) {
46                 if (i+1 < n && (a[i]%2 && a[i+1]%2 == 0)|| (a[i]%2 == 0 && a[i+1]%2) ) {   // one odd one even
47                     ans += 2;
48                     a[i+1] = 2;
49                 }
50             }
51             printf("%d\n", ans);
52        }
53     }
54     return 0;
55 }

方法二:dp

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 using namespace std;
 6
 7 const int inf = 10000000;
 8 const int maxn = 1e5 + 5;
 9 int a[maxn];
10 // dp[i][0]: 前i-1个数为偶数,第i个数为偶数的最少操作次数
11 // dp[i][1]:  前i-1个数为偶数,第i个数为奇数的最少操作次数
12 int dp[maxn][2];
13
14 int GCD(int b1, int b2)
15 {
16     if (b2 == 0)
17         return b1;
18     return GCD(b2, b1%b2);
19 }
20
21 int main()
22 {
23     #ifndef ONLINE_JUDGE
24         freopen("in.txt", "r", stdin);
25     #endif // ONLINE_JUDGE
26
27     int n;
28     while (scanf("%d", &n) !=EOF) {
29        scanf("%d", &a[0]);
30        int t=a[0], cnt = 0;
31
32        for (int i = 1; i < n; i++) {
33             scanf("%d", &a[i]);
34             t = GCD(t, a[i]);
35             if (t > 1) { cnt++; }
36        }
37        printf("YES\n");
38        if ( cnt == n-1 ) { printf("0\n"); }  // all 有公约数
39
40        else {
41             memset(dp, 0, sizeof(dp));
42             dp[0][!(a[0]%2)] = inf;
43
44             for (int i = 1; i < n; i++) {
45                 if (a[i]%2) {     // odd
46                     dp[i][0] = min(dp[i-1][0]+2, dp[i-1][1]+1);
47                     dp[i][1] = min(dp[i-1][0], inf);
48                 }
49                 else {
50                     dp[i][0] = min(dp[i-1][0], dp[i-1][1]+2);
51                     dp[i][1] = inf;
52
53                 }
54             }
55             printf("%d\n", dp[n-1][0]);
56        }
57     }
58     return 0;
59 }

时间: 2024-08-24 15:37:04

codeforces 798C.Mike and gcd problem 解题报告的相关文章

codeforces 798C Mike and gcd problem

C.Mike and gcd problem Mike has a sequence A?=?[a1,?a2,?...,?an] of length n. He considers the sequence B?=?[b1,?b2,?...,?bn] beautiful if the gcd of all its elements is bigger than 1, i.e. . Mike wants to change his sequence in order to make it beau

【算法系列学习】codeforces C. Mike and gcd problem

C. Mike and gcd problem http://www.cnblogs.com/BBBob/p/6746721.html 1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 8 using namespace std; 9 const

798C - Mike and gcd problem

题意 通过将一组序列中 ai与ai+1 变为 ai-ai+1 与ai+ai+1 的操作将这组序列的gcd变成不为1. 看了题解才会写== ,所以叫做补提嘛QWQ,当d|a && d|b 时 d|ax+by ,即 d|ai-ai+1 d|ai+ai+1 时,可得 d|2ai, d|2ai+1 从而新序列的gcd一定为2,所以先求出所有数字的gcd(因为我太菜的原因不知道算gcd的复杂度其实不高,log(max(a,b))这样,如果不等于1,直接输出0. 然后再贪心扫两遍就行. #includ

codeforces 505A. Mr. Kitayuta&#39;s Gift 解题报告

题目链接:http://codeforces.com/problemset/problem/505/A 题目意思:给出一个长度不大于10的小写英文字符串 s,问是否能通过在字符串的某个位置插入一个字母,使得新得到的字符串成为回文串. /**************************************(又到自我反省时刻) 做的时候,通过添加一个单位使得长度增加1,找出中点,检验前一半的位置,找出对称位置替换成对应的前一半位置的字符,然后原字符串剩下的部分追加到后面,再判断回文.但是由于

G - Mike and gcd problem

G - Mike and gcd problem Mike has a sequence A?=?[a1,?a2,?...,?an] of length n. He considers the sequence B?=?[b1,?b2,?...,?bn] beautiful if the gcd of all its elements is bigger than 1, i.e. . Mike wants to change his sequence in order to make it be

CF Round410 C. Mike and gcd problem

C. Mike and gcd problem 一奇一偶需要两次操作,两个奇数需要一次操作. 798D - Mike and distribution In the beginning, it's quite easy to notice that the condition " 2·(ap1?+?...?+?apk) is greater than the sum of all elements in A " is equivalent to " ap1?+?...?+?a

[poj 2480] Longge&#39;s problem 解题报告 (欧拉函数)

题目链接:http://poj.org/problem?id=2480 题目大意: 题解: 我一直很欣赏数学题完美的复杂度 #include<cstring> #include<algorithm> #include<cstdio> #include<iostream> #include<cmath> using namespace std; typedef long long ll; const int N=(1<<31)+15;

Codeforces Round #410 (Div. 2)C. Mike and gcd problem(数论)

传送门 Description Mike has a sequence A = [a1, a2, ..., an] of length n. He considers the sequence B = [b1, b2, ..., bn] beautiful if the gcd of all its elements is bigger than 1, i.e. . Mike wants to change his sequence in order to make it beautiful.

codeforces 582A. GCD Table 解题报告

题目链接:http://codeforces.com/problemset/problem/582/A 网上很多题解,就不说了,直接贴代码= = 官方题解: http://codeforces.com/blog/entry/20692 1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <algorithm>