zoukankan      html  css  js  c++  java
  • bzoj3957

    数学+模拟

    细节很多

    首先我们发现,如果两个区间已经包含,那么可以输出empty,一个数能通过变换得到另一个区间的数,这个区间的大小必须小于等于终点区间的大小。加法不会改变区间大小,只有乘法会改变,而且每次乘法会使区间大小扩大m倍。其实我们发现,最终一个数会变成p*x+y,x是m的几次幂,y是一个a乘上一些m的幂再加上一些a.x=m^l+a(A0*m^l+A1*m^n-1+...+An)所以我们就是要把后面的东西展开。

    但是题目要求操作数最少且字典序最小。所以我们要枚举最大的次数,枚举次数时还要保证次数最少。保证次数最少应该更多用乘法保证,所以就是把一些加法换成乘法,也应该尽量用高次代替低次,所以我们每次枚举次数,然后枚举每位,把每位用尽量大的数替代,后面的数清零,然后判断。字典序的判断比较鬼畜。

    当m=0或m=1时把m赋成极大值,这样就可以保证m不会乘,impossible就是先把ans变成一个极大值,然后判断。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<ll, char> PII;
    vector<PII> ans;
    ll a, m, p, q, r, s;
    int kase;
    bool cp(vector<PII> &A, vector<PII> &B)
    {
        ll s1 = 0, s2 = 0;
        for(int i = 0; i < A.size(); ++i)
            s1 += A[i].first;
        for(int i = 0; i < B.size(); ++i)
            s2 += B[i].first;
    //    printf("%d %d
    ", A.size(), B.size());
        if(s1 != s2)
            return s1 < s2;
        int lim = min(A.size(), B.size());
        for(int i = 0; i < lim; ++i)
        {
            if(A[i].second != B[i].second)
                return A[i].second < B[i].second;
            if(A[i].first != B[i].first)
            {
                if(A[i].second == 'A')
                    return A[i].first > B[i].first;
                else 
                    return A[i].first < B[i].first;
            }
        }
        return A.size() < B.size();
    }
    void update(int x, ll target)
    {
    //    printf("x=%d target=%d
    ", x, target);
        vector<PII> v; v.clear();
        for(int i = 0; i < x; ++i)
        {
            if(target % m)
                v.push_back(make_pair(target % m, 'A'));
            target /= m;
            if(v.empty() || v.back().second == 'A')
                v.push_back(make_pair(1ll, 'M'));
            else
                ++v.back().first; 
        }
        if(target)
            v.push_back(make_pair(target, 'A'));
        reverse(v.begin(), v.end());
    //    for(int i = 0; i < v.size(); ++i)
    //        printf(" %d%c", v[i].first, v[i].second);
    //    printf("
    ");
        if(cp(v, ans))
            swap(ans, v);    
    }
    void process(int low, int high, int m, int t)
    {
        for(int i = 0, j = 1; i <= t; ++i, j *= m)
        {
            int x = (low + j - 1) / j * j; 
            if(x > high)
                break;
            update(t, x);
        }
    }
    int main()
    {
    //    freopen("output.txt", "w", stdout);
        while(scanf("%lld%lld%lld%lld%lld%lld", &a, &m, &p, &q, &r, &s))
        {
            if(!a && !m && !p && !q && !s && !r)
                break;
            ans.clear();
            if(m == 0 || m == 1)
                m = 1000000010ll;
            printf("Case %d:", ++kase);
            if(p >= r && q <= s)
            {
                printf(" empty
    ");
                continue;
            }
            ans.push_back(make_pair(2000000000ll, 'A'));
            for(int mul = 0; q <= s && q - p <= s - r; ++mul, p *= m, q *= m)
            {
                ll minadd = max(0ll, (r - p + a - 1) / a), maxadd = (s - q) / a; 
                if(minadd > maxadd)
                    continue;
                process(minadd, maxadd, m, mul); //mul:最多乘mul次 
            }
            if(ans[0].first == 2000000000ll)
            {
                printf(" impossible
    ");
                continue;
            }
            for(int i = 0; i < ans.size(); ++i)
                printf(" %lld%c", ans[i].first, ans[i].second);
            printf("
    ");
        }
    //    fclose(stdout);
        return 0;
    }
    View Code
  • 相关阅读:
    SpringMVC 拦截器
    Download And Uploader
    Spring 作用域传值
    Spring MVC 视图解析 VIEW
    SpringMVC自动注入
    cmake编译opencv4项目遇到opencv_found set to false问题
    vscode配置c++开发环境
    CMakeLists.txt样本
    mysql5.7高版本加载低版本sql文件,时间不能为0000-00-00格式错误
    log4j.properties配置
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7098301.html
Copyright © 2011-2022 走看看