最大公约数c语言算法牛客,[Nowcoder]2020牛客寒假算法基础集训营4

20200211 第四场

进度(4 / 10) 未完成:C / F / G / H / I / J

A、欧几里得

1、链接

2、题面

欧几里得算法是一种求最大公约数的有效算法,在算法竞赛中很常用。

这个算法的 Python 实现如下:

def gcd(a,b):

if b == 0:

return a

return gcd(b,a%b)

现在,如果已知 gcd(a,b) 共递归了 n次,求所有可能的a,b中满足a>b>=0且a+b最小的一组的a与b之和。

3、思路

打表找规律。然后就发现是个斐波那契数列了。

4、代码

1 #include

2 using namespacestd;3

4 #define MAXN 105

5 typedef long longll;6

7 ll a[MAXN], b[MAXN], mx, t;8

9 intmain() {10 cin >>t;11 for (int i = 1; i <= t; i++) cin >> a[i], mx =max(a[i], mx);12 b[0] = 1, b[1] = 3, b[2] = 5;13 for (int i = 3; i <= mx; i++) b[i] = b[i - 1] + b[i - 2];14 for (int i = 1; i <= t; i++) cout << b[a[i]] <

B、括号序列

1、链接

2、题面

注意:数据已加强并进行了rejudge

给出一个仅包含'[',']','(',')','{','}'六种字符的括号序列,判断其是否合法。

空串是一个合法的括号序列

如果A, B 都是合法的括号序列,那么AB也是合法的括号序列

如果A是合法的括号序列,(A) , [A], {A}都是合法的括号序列

3、思路

标准栈问题。

4、代码

1 #include

2 using namespacestd;3

4 #define MAXN 1000005

5

6 stack s;7 charch[MAXN];8 intl;9

10 intmain() {11 cin >> ch + 1, l = strlen(ch + 1);12 for (int i = 1; i <= l; i++) {13 if (ch[i] == '(' || ch[i] == '[' || ch[i] == '{') s.push(ch[i]);14 else{15 if (s.empty()) cout << "No", exit(0);16 int o =s.top();17 if (ch[i] == ')' && o == '(' || ch[i] == ']' && o == '[' || ch[i] == '}' && o == '}') s.pop();18 else cout << "No", exit(0);19 }20 }21 cout << (s.empty() ? "Yes" : "No");22 return 0;23 }

D、子段异或

1、链接

2、题面

输入一个数列a,你需要输出其中异或值为0的不同子段的数量。一个子段 [l,r] (1≤l≤r≤n)的异或值为al⊕al+1⊕al+2⊕…⊕ar,其中⊕符号代表异或运算。

两个子段被视为相同的,当且仅当其开始和结束位置均对应相同。

3、思路

先求了一下前缀异或s[],发现当且仅当s[l - 1] = s[r],[l, r]的异或值为0,则记录下所有前缀异或值,用map记录每一个出现过的值和出现次数,如果出现次数为i,则可以得到(i - 1) * i / 2个满足条件的子段。

4、代码

1 #include

2 using namespacestd;3

4 #define MAXN 200005

5 typedef long longll;6

7 map mp;8 ll a[MAXN], b[MAXN], n, c[MAXN], o, ans;9

10 intmain() {11 cin >>n;12 for (int i = 1; i <= n; i++) cin >>a[i];13 b[1] = a[1], mp[0] = 0, c[0]++;14 for (int i = 1; i <= n; i++) {15 b[i] = i == 1 ? a[i] : b[i - 1] ^a[i];16 if (!mp.count(b[i])) mp[b[i]] = ++o;17 c[mp[b[i]]]++;18 }19 for (int i = 0; i <= o; i++) ans += c[i] * (c[i] - 1) / 2;20 cout <

E、最小表达式

1、链接

2、题面

给出一个包含数字1-9和加号的字符串,请你将字符串中的字符任意排列,但每种字符数目不变,使得结果是一个合法的表达式,而且表达式的值最小。输出那个最小表达式的值

合法的表达式的定义如下:

- 一个数字,如233,是一个合法的表达式

- A + B是合法的表达式,当且仅当 A , B 都是合法的表达式

保证给出的表达式经过重排,存在一个合法的解。

3、思路

首先将数字和加号分离,由于使总和最小,所有尽可能使数平均。设加号的个数x,则分出的数的个数为x - 1。将数字从大到小排列,然后从个位开始依次将这些数字填入这x - 1个数,可证这样总和最小。

4、代码

1 #include

2 using namespacestd;3

4 #define MAXN 500005

5

6 int ans[MAXN], x = 1, l, hav;7 charch[MAXN];8

9 structcmp {10 bool operator () (char a, charb) {11 return a >b;12 }13 } cmpx;14

15 intmain() {16 cin >> ch + 1, l = strlen(ch + 1);17 sort(ch + 1, ch + l + 1, cmpx);18 while (ch[l] == '+') x++, l--;19 for (int i = 0; i < l / x; i++)20 for (int j = 1; j <= x; j++) {21 ans[i] += ch[i * x + j] - '0';22 ans[i + 1] += ans[i] / 10, ans[i] %= 10;23 }24 if (l %x)25 for (int i = 1; i <= l % x; i++) {26 ans[l / x] += ch[l / x * x + i] - '0';27 ans[l / x + 1] += ans[l / x] / 10, ans[l / x] %= 10;28 }29 for (int i = l / x + 1; i >= 0; i--)30 if (ans[i] || hav) cout << ans[i], hav = 1;31 return 0;32 }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值