转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
题意:给出若干个区间,区间可以左右移动,所有区间移动幅度总和最多为K。问最多有多少个lucky number同时在n个区间中。
http://codeforces.com/contest/121/problem/D
感觉还不错的题,另外这周太水了,难得做个题。。。
首先处理出1e18以内的所有lucky number。
然后大致想法是two points处理lucky number的某个区间。
然后就是要check一下是否可行。
第一个条件是区间长度不能小于所有区间中最短的。。。
第二个条件是看所有区间能否移动到指定区间。
左右端点分开处理,对于左端点,如果目标为lucky[i],那么所有左端点 > lucky[i]的都必须移动过来。
排序后又是一次two points。右端点同样处理。
结束。。。注意下高精度
import java.util.*;
import java.io.*;
import java.lang.reflect.Array;
import java.math.*;
public class Main {
public static void main(String[] args) {
InputStream inputStream = System.in;
OutputStream outputStream = System.out;
InputReader in = new InputReader(inputStream);
PrintWriter out = new PrintWriter(outputStream);
int t = 1;
Task solver = new Task();
while ((t --) > 0)
solver.solve(in, out);
out.close();
}
}
class Task{
static int N = 100005;
static int M = (1 << 19) - 2;
static long INF = 1000000000000000000L;
long l[] = new long [N] , r[] = new long [N];
long lucky[] = new long[M];
BigInteger lsum[] = new BigInteger[M];
BigInteger rsum[] = new BigInteger[M];
void Init () {
int c = 0;
for (int i = 1 ; i <= 18 ; i ++) {
for (int j = 0 ; j < (1 << i) ; j ++) {
long t = 0;
for (int k = 0 ; k < i ; k ++) {
if ((j & (1 << k)) != 0)
t = t * 10 + 7;
else t = t * 10 + 4;
}
lucky[c ++] = t;
}
}
Arrays.sort(lucky);
}
void solve (InputReader cin , PrintWriter cout) {
Init ();
int n = cin.nextInt();
long k = cin.nextLong();
long minlen = INF;
for (int i = 0 ; i < n ; i ++) {
l[i] = cin.nextLong();
r[i] = cin.nextLong();
minlen = Math.min(minlen, r[i] - l[i] + 1);
}
Arrays.sort(l , 0 , n);
Arrays.sort(r , 0 , n);
BigInteger sum = BigInteger.ZERO;
for (int i = M - 1 , j = n - 1 ; i >= 0 ; i --) {
while (j >= 0 && lucky[i] <= l[j]) {
sum = sum.add (BigInteger.valueOf(l[j]));
j --;
}
lsum[i] = sum.subtract(BigInteger.valueOf(n - j - 1).multiply(BigInteger.valueOf(lucky[i])));
}
sum = BigInteger.ZERO;
for (int i = 0 , j = 0 ; i < M ; i ++) {
while (j < n && r[j] <= lucky[i]) {
sum = sum.add (BigInteger.valueOf(r[j]));
j ++;
}
rsum[i] = BigInteger.valueOf(lucky[i]).multiply(BigInteger.valueOf(j)).subtract(sum);
}
int ans = 0;
for (int i = 0 , j = 0 ; i < M ; i ++) {
while (i > j || j < M && lucky[j] - lucky[i] + 1 <= minlen && lsum[i].add (rsum[j]).compareTo(BigInteger.valueOf(k)) <= 0) j ++;
ans = Math.max (ans , j - i);
}
cout.println(ans);
}
}
class InputReader {
public BufferedReader reader;
public StringTokenizer tokenizer;
public InputReader(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream));
tokenizer = null;
}
public String next() {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
try {
tokenizer = new StringTokenizer(reader.readLine());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return tokenizer.nextToken();
}
public int nextInt() {
return Integer.parseInt(next());
}
public long nextLong() {
return Long.parseLong(next());
}
public double nextDouble() {
return Double.parseDouble(next());
}
public BigInteger nextBigInteger() {
return new BigInteger(next());
}
}