zoukankan      html  css  js  c++  java
  • 洛谷P2054 [AHOI2005]洗牌(扩展欧几里德)

    洛谷题目传送门

    来个正常的有证明的题解

    我们不好来表示某时刻某一个位置是哪一张牌,但我们可以表示某时刻某一张牌在哪个位置。

    设数列({a_{i_j}})表示(i)号牌经过(j)次洗牌后的位置,我们试着来递推一下

    首先,如果此刻牌在上面一叠,显然(a_{i_{j+1}}=2a_{i_j})

    接着,如果这张牌在下面一叠,那么(a_{i_{j+1}}=2(a_{i_j}-frac n2)-1=2a_{i_j}-(n+1)),应该也很好推出来

    写在一起,观察一下

    [a_{i_{j+1}}=egin{cases}2a_{i_j}qquadqquad ,a_{i_j}leqfrac n2\2a_{i_j}-(n+1),a_{i_j}>frac n2end{cases} ]

    诶,两个式子都有一个系数(2)呢!那我们可不可以把它看成模(n+1)意义下的结果呢?

    于是可以进一步得到(a_{i_j}equiv2^mi(mod n+1))(i)就是(a_{i_0})

    题目已经知道了(a_{i_j}),来求(i),不就是一个线性同余不定方程么?exgcd搞一下就好啦!因为(gcd(2^m,n+1)=1),所以根本不用像青蛙的约会那样麻烦。

    看楼上大佬用异或写swap?!第一次见的蒟蒻表示只能Orz。然后蒟蒻就把exgcd这个函数成功压缩到了一行。。。。。。

    #include<cstdio>
    #define LL long long
    LL n,m,l,x=1,y;
    LL qpow(LL b,LL k){//快速幂求2^m
    	LL a=1;
    	while(k){
    		if(k&1)a*=b,a%=n+1;
    		b*=b,b%=n+1;
    		k>>=1;
    	}
    	return a;
    }
    void exgcd(LL a,LL b){//一行exgcd233
    	if(b)exgcd(b,a%b),(y^=x^=y^=x)-=a/b*x;
    }
    int main(){
    	scanf("%lld%lld%lld",&n,&m,&l);
    	exgcd(qpow(2,m),n+1);
    	printf("%lld
    ",(l*x%(n+1)+n+1)%(n+1));//注意化成最小正整数
    	return 0;
    }
    
  • 相关阅读:
    mysql学习日志
    Python学习day10 Javascript/Jquery
    Python学习day07 多线程多进程及主机管理
    Linux基本命令
    django 用户认证/Excel导入Mysql
    转:iptables详解
    Python django前端导入Excel脚本
    Python学习day08 分布式监控系统开发实战
    Subline Text2
    MySQL 常用函数分析
  • 原文地址:https://www.cnblogs.com/flashhu/p/9152921.html
Copyright © 2011-2022 走看看