P4109 [HEOI2015]定价
P4109 [HEOI2015]定价
题目
思路
直接上算法:
分块
为了尽可能平均,把[0,1e9]
分成1e5个块,第i个块为[i*1e4,(i+1)*1e4)
,不难想到,每一个块的"荒谬度最低的价格"为左端点,即i*1e4
,
然后就是分块的老套路:
令p表示l所属的块,q表示r所属的块
p==q
:暴力else
:把当前区间分成三段:[l,(p+1)*1e4],[(p+1)*1e4,(q-1)*1e4),[q*1e4,r]
(注意区分括号的意义,还有就是区间重合对结果无影响),结合上面的结论(加粗部分),可以在O(sqrt(r-l))级别内求出答案
详见代码:
代码
AC程序(tested.cpp)
#include <iostream>
using namespace std;
int a[200010];
int count(int x) {
while(x % 10 == 0)x/=10;
int res = (x % 10 == 5 ? -1 : 0);
while(x != 0) {
x /= 10;
res += 2;
}
return res;
}
int GetMin(int l , int r){//暴力求[l,r]的"荒谬度最低的价格"
int minn = (1 << 29) , ans;
for(int i = l ; i <= r ; i++) {
int tmp = count(i);
if(tmp < minn)
minn = tmp , ans = i;
}
return ans;
}
int main() {
int t;
cin >> t;
while(t--) {
int l ,r;
int minn = (1 << 29) , ans;
cin >> l >> r;//好久没用过cin/cout了,庆祝一下
int p = l / 10000 , q = r / 10000;
if(p == q)
ans = GetMin(l , r);
else {
ans = (p + 1) * 10000;
minn = count(ans);
for(int i = ans ; i < r ; i += 10000) {//[(p+1)*1e4,(q-1)*1e4)
if(count(i) < minn)
minn = count(i) , ans = i;
}
int tmp = GetMin(l , (p + 1) * 10000);//[l,(p+1)*1e4]
if(count(tmp) < minn)
minn = count(tmp) , ans = tmp;
tmp = GetMin(q * 10000 , r);//[q*1e4,r]
if(count(tmp) < minn)
minn = count(tmp) , ans = tmp;
}
cout << ans << endl;
}
return 0;
}
暴力(std.cpp)
#include <iostream>
using namespace std;
int count(int x) {
while(x % 10 == 0)x/=10;
int res = (x % 10 == 5 ? -1 : 0);
while(x != 0) {
x /= 10;
res += 2;
}
return res;
}
int main() {
int t;
cin >> t;
while(t--) {
int l ,r;
cin >> l >> r;
int minn = (1 << 29) , ans;
for(int i = l ; i <= r ; i++) {
int tmp = count(i);
if(tmp < minn)
minn = tmp , ans = i;
}
cout << ans << endl;
}
return 0;
}
对拍用随机数生成器(random.cpp)
#include <bits/stdc++.h>
using namespace std;
int random(int r , int l = 1) {
return r == l ? l : ((long long)rand() * rand() % (r - l) + l);
}
int main() {
srand((unsigned)time(0));
int t = random(100);
cout << t << endl;
for(int i = 1 ; i <= t ; i++) {
int l = random(100000000) , r = l + random(1000000);//说明:这里是为了保证暴力程序不超时,可自行加大数据强度
cout << l << ' ' << r << endl;
}
return 0;
}
对拍控制
#include <bits/stdc++.h>
using namespace std;
int main() {
while(true) {
system("random.exe > input.txt");
puts("random");
system("std.exe < input.txt > output1.txt");
puts("std");
system("tested < input.txt > output2.txt");
puts("tested");
if(system("fc output1.txt output2.txt")) {
cout << "WA";
system("start input.txt");
return 0;
}
}
return 0;
}