CF70C Lucky Tickets

题意描述:

洛谷

(rev(i)) 表示把 (i) 的每一位翻转之后所得到的数。

如果 $a imes b = rev(a) imes rev(b) $ , 则称数对 ((a,b)) 是合法的。

(f(n,m)) 表示:(ileq n,jleq m), 且数对 ((i,j)) 是合法的数对的个数。

现在给你三个数 (x_{max},y_{max},w), 让你求一组 ((x,y)) 满足:(f(x,y)geq w)(xleq x_{max},yleq y_{max})(x imes y) 最小,无解则输出 (-1)

数据范围: (x_{max},y_{max}leq 10^5, wleq 10^7)

solution:

( map) + 双指针。

首先我们考虑一个问题就是怎么求出 (f(n,m))

我们把 (a imes b = rev(a) imes rev(b)) 变形为:({aover rev(a)} = {rev(b)over b})

然后可以先开个 (map) 存一下 (aover rev(a)) 出现的次数, 然后在枚举一下 (b) ,那么 (b)(f(n,m)) 的贡献就是 (rev(b)over b) 的出现次数。

在能求出来 (f(n,m)) 之后,我们这道题就很好做了。

我们可以先扫一遍求出 (f(x_{max},y_{max})) ,无解的情况就是 (f(x_{max},y_{max}) > w)

至于有解的情况,我们维护两个指针 (l,r) 表示 当 (x=l) 时,符合条件的 (y) 最小为 (r)

同时维护一个 变量 (cnt), 表示当前 (f(l,r)) 的值。

不难发现,随着 (l) 的递增, (r) 一定是单调递减的。

所以我们可以拿双指针维护一下,同时再开两个 (map) 用来统计 (aover rev(a))(rev(b)over b) 出现的次数。

(l,r) 指针移动的时候, 用 (map) 就可以直接维护出指针移动之后 (cnt) 的值 (类似于莫队的指针移动)。

复杂度: (O(nlogn))

code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<map>
using namespace std;
int maxx,maxy,w,l,r,ans,ansl,ansr,cnt,sum;
map<double,int> t1,t2;
inline int read()
{
    int s = 0, w = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
    return s * w;
}
int rev(int x)
{
    int res = 0;
    while(x)
    {
        res = res * 10 + x % 10;
        x /= 10;
    }
    return res;
}
int main()
{
    maxx = read(); maxy = read(); w = read(); ans = 1e10;
    for(int i = 1; i <= maxx; i++) t1[1.0*i/rev(i)]++;
    for(int i = 1; i <= maxy; i++) sum += t1[1.0*rev(i)/i];//求f(maxx,maxy)
    if(sum < w) printf("%d
",-1);//无解的情况
    else
    {
        l = maxx, r = 0;
        while(l && r <= maxy)
        {
            while(cnt < w && r <= maxy)
            {
            	r++;
                t2[1.0*rev(r)/r]++;
                cnt += t1[1.0*rev(r)/r];//r指针对cnt的贡献
            }
            if(cnt >= w && r*l < ans)
            {
                ans = r*l;
                ansl = l; ansr = r;
            }
            cnt -= t2[1.0*l/rev(l)];//l向左移对cnt的贡献
            t1[1.0*l/rev(l)]--;
            l--;
        } 
	printf("%d %d
",ansl,ansr);
    }
   
    return 0;
}
原文地址:https://www.cnblogs.com/genshy/p/14438382.html