10.18 携程笔试编程题1、2、4题解
1. 给你一个整数x和k,让你反转x的前k位。
a, k = input().split() k = int(k) print(int(a[k-1::-1]+a[k:]))
2. 给你一个长度小于等于10的字符串,求合法字符串的个数。
合法字符串:串中所有相邻两个字符都不相同
#include <bits/stdc++.h> using namespace std; int main() { string s; cin >> s; const int n = s.length(); sort(s.begin(), s.end()); int cnt = 0; do { bool ok = true; for (int i = 1; i < n; i++) { if (s[i] == s[i-1]) { ok = false; break; } } cnt += ok; } while (next_permutation(s.begin(), s.end())); cout << cnt << endl; return 0; }
3. 题目大致意思是给定4个数,a,b,low,high。
每次操作你可以给a加上x,其中low<=x<=high。
求最终使a=b的最小和最大操作数。
无解输出-1.
条件:0 <= a <= b <= 1e9
1 <= low <= high <= 1e9
这题不会。有会的大佬麻烦给个思路,谢谢。
4. 给你一个数组和一个数x,从数组中任取两个数,求满足这两个数的乘积末尾至少有x个0的方案数。
思路:
对于两个数a和b,如果它们的因子10、2、5的个数分别为x1, x2, x3,y1,y2,y3,那么它们的乘积末尾总共有x1+y1+min(x2, y3)+min(x3, y2)。可以记录下数组中含有不同10、2、5因子个数各有多少个,剩下的就是组合问题了。
假如有x个a和y个b,而a*b一共能产生target个0。如果a和b相等,则x和y也相等,这种情况就相当于x个相同数中取2个,一共有Cn2=n*(n-1)/2种方案;如果a和b不相等,则一共有x*y/2种方案。
因为2**31>1e9,5**14>1e9,所以最大计算量应该为(31*14*10)**2,大概在8个数量级的样子。数组大小1e5,双重循环暴力判断运算量就是10个数量级了。
补充:
再想了一下,这里可以只考虑因子2和5,可以再减两个数量级,这里就不实现了。
#include <bits/stdc++.h> using namespace std; int main() { int n, x; cin >> n >> x; vector<int> v(n); for (int i = 0; i < n; i++) { cin >> v[i]; } int cnt[11][32][15]{0}; for (int i = 0; i < n; i++) { int val = v[i]; int f_10 = 0, f_2 = 0, f_5 = 0; while (val%10 == 0) { val /= 10; f_10 ++; } while (val%2 == 0) { val /= 2; f_2 ++; } while (val%5 == 0) { val /= 5; f_5 ++; } cnt[f_10][f_2][f_5] ++; } long long nums[19]{0}; for (int i = 0; i < 11; i++) { for (int j = 0; j < 32; j++) { for (int k = 0; k < 15; k++) { for (int ii = 0; ii < 11; ii++) { for (int jj = 0; jj < 32; jj++) { for (int kk = 0; kk < 15; kk++) { int cnt_0 = i+ii+min(j, kk)+min(jj, k); nums[cnt_0] += i==ii&&j==jj&&k==kk ? 1LL*cnt[i][j][k]*(cnt[i][j][k]-1) : 1LL*cnt[i][j][k]*cnt[ii][jj][kk]; } } } } } } long long ans = 0; for (int i = x; i < 19; i++) { ans += nums[i]/2; } cout << ans << endl; return 0; }