zoukankan      html  css  js  c++  java
  • bzoj5213: [Zjoi2018]迷宫

    好题!话说省选的都开始构造了吗

    由于有K的倍数的限制所以不妨取模,先建K个点表示0~K-1这些数,第i个点向[i*m,i*m+m]建边。不难发现这是合法的但不一定是最优的

    考虑合并等价的点,首先从直观上考虑,当两个点能够转移到的点相同时,它们一定可以合并,但是能够合并的点远远不止这些

    考虑一般化,对于两个节点x,y,假设x*m^q=y*m^q (mod K) 那么只要在q步中x和y没有到达0节点的方案,那么x和y就可以合并

    具体的,首先0一定不能被删掉,现在考虑q=1时,1~K-1中等价点

    把所有数乘m,只有gcd(m,K)的倍数才能表示出来,对于变成同一个数的点就可以去重了(不过并不需要具体实行这一步骤)

    然后,对于能够表示出的能够到达0节点的点,无论如何都没有办法合并,把其中还存在的点计入答案(q=1都存在,但是q递增后就变化了)

    让q++,把乘完m得出的每个不同的数拿出来继续进行上述操作,每一轮相当于把在第q轮可以到达0节点且在之前的轮中没有被删的节点计入答案,再把恰好在第q轮等价的点去重(感觉用unique表达更贴切)

     

    现在我们目标是快速模拟这个过程,令f(l,K),表示现在要解决的数值域为[1,l],模数为K,考虑如何递归求解

    若l<=K/d,没有溢出不会相交,直接返回l即可

    仅考虑q=1的情况,在后期继续递归的时候再考虑满足条件。对于以前可以到达0的数为[(K-l),K],那么此时已经可以到达0的数为[K-m*(K-l),K],在这个值域的数的个数为m*(K-l)/gcd(m,K),计入答案(这里可能有点玄学,可以先看下面再回来看)

    为了保证值域连续,当把数都变成gcd(m,K)的倍数后,令所有数都除以gcd(m,K)变为连续,此时上界为(K-m*(K-l))/gcd(m,K)(注意m*(K-l)是可以到达0的数的个数,是要保留的部分不参与递归了。用总数减去保留的数量剩下的再变成压缩同余系),相应的同余系大小K也应该变成K/gcd(m,K)

    最终继续递归求f((K-m*(K-l))/gcd(m,K),K/gcd(m,K)),注意会有l>K的情况,此时会取遍K/gcd(m,K)直接返回即可

    有一个疑问是对于值的改变是否m也应该随之改变?

    ccosi(远行客)的说法:(感谢大佬的解答)

    你是不是觉得应该乘上m/d?
    事实上(k-l)这里已经/d了,所以是直接乘m,下一层的k-m(k-l)就是上一层的k/d-m((k-l)/d)

    ta的blog

    我的理解是对于每个数我们是乘上而不是加上m,那么域的变化是不影响乘法的

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    LL gcd(LL a,LL b){return (a==0)?b:gcd(b%a,a);}
     
    LL m;
    LL solve(LL l,LL K)
    {
        LL d=gcd(m,K);
        if(l<=K/d)return l;
        if(K<=(double)m*(K-l))return K/d;
        else return m/d*(K-l)+solve((K-m*(K-l))/d,K/d);
    }
     
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            LL K;
            scanf("%lld%lld",&m,&K);
            printf("%lld
    ",solve(K-1,K)+1);
        }
         
        return 0;
    }
    
  • 相关阅读:
    Android和C#实时视频传输Demo
    cocos2d-x3.0 windows 环境配置
    WPF六个控制概述
    高度并行的指令级的超级处理器
    Oracle存储过程的简单示例
    SharePoint Search之(两)持续抓取Continues crawl
    第28周三
    第28周二
    第28周一
    第27周日
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/10710941.html
Copyright © 2011-2022 走看看