题目链接:CDOJ 761 LoveZx与期末考试
题意:给定两个大整数
a
和
思路:直接模拟是可以做的,但不过太过复杂。我们尝试去二分这个最优解,对当前的判定值
mid
,我们只需要求出
b
在
假设
n
位的整数
考虑移动
a[1]−a[n]
里面前
mid
大的数到高位:
我们不能只移动前
mid
大的数,因为
a[1]==b[1]
同理
a[2]
。假设从第一位开始有
num
个连续位满足
a[i]==b[i]
,这样的话,这
num
个数是不需要移动的,因为已经是最优了。也就是说,对当前的
mid
次移动,我们可以看做是移动
a[1]−a[n]
里面前
(mid+num)
大的数到高位。然后就是把剩余的数按原顺序填上,这样就得到了移动
mid
次的最优值。填数的时候,需要把移动的
mid
个数标记上。
这样时间复杂度
O(nlogn)
AC
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#define PI acos(-1.0)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define fi first
#define se second
#define ll o<<1
#define rr o<<1|1
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 1e5 + 10;
const int pN = 1e6;// <= 10^7
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
void getmax(int &a, int b) {a = max(a, b); }
void getmin(int &a, int b) {a = min(a, b); }
void add(LL &x, LL y) { x += y; x %= MOD; }
int a[MAXN], b[MAXN];
char x[MAXN], y[MAXN];
int lx, ly;
bool cmp(int x, int y) {
return x > y;
}
void get(int *c, char s[]) {
int len = strlen(s);
for(int i = 0; i < len; i++) c[i] = s[i] - '0';
}
int d[MAXN], c[MAXN], use[10];
bool judge(int cnt, int num)
{
if(lx < ly) return true;
else if(lx > ly) return false;
for(int i = 0; i <= 10; i++) {
use[i] = 0;
}
CLR(d, 0);
for(int i = 0; i < min(ly, cnt+num); i++) {
d[i] = c[i];
if(i >= num) {
use[c[i]]++;
}
}
int top = ly-1;
for(int i = ly-1; i >= 0 && top >= min(ly, cnt+num); i--) {
if(use[b[i]]) {
use[b[i]]--;
}
else {
d[top--] = b[i];
}
}
// cout << cnt << endl;
// for(int i = 0; i < ly; i++) {
// cout << d[i] << ' ';
// }
// cout << endl;
for(int i = 0; i < ly; i++) y[i] = d[i] + '0';
return strcmp(y, x) > 0;
}
int main()
{
int t; scanf("%d", &t);
while(t--)
{
scanf("%s%s", x, y);
lx = strlen(x), ly = strlen(y);
CLR(a, 0); CLR(b, 0); CLR(c, 0);
get(a, x); get(b, y);
for(int i = 0; i < ly; i++) {
c[i] = b[i];
}
sort(c, c+ly, cmp); int num = 0;
for(int i = 0; i < ly; i++) {
if(c[i] == b[i]) {
num++;
}
else break;
}
int l = 0, r = ly;
int ans = -1;
while(r >= l) {
int mid = (l + r) >> 1;
if(judge(mid, num)) {
ans = mid;
r = mid-1;
}
else {
l = mid+1;
}
}
if(ans == -1) {
printf("Poor LoveZx\n");
}
else {
printf("%d\n", ans);
}
}
return 0;
}