zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    常用linux命令
    console页面进去太慢优化
    CentOS7 查看最大线程连接数
    外部ssh连接Ubuntu系统
    Ubantu 防火墙管理
    oracle 闪回
    oracle用户密码过期
    base64编码原理
    Linux 备份数据库mysql
    python静态方法-类方法
  • 原文地址:https://www.cnblogs.com/genshy/p/14438382.html
Copyright © 2011-2022 走看看