首页 > 其他分享 >[AHOI2005] SHUFFLE 洗牌

[AHOI2005] SHUFFLE 洗牌

时间:2024-03-29 15:22:06浏览次数:17  
标签:AHOI2005 int ll 洗牌 long return ans SHUFFLE mod

image

这是一道逆元的模板题。

看到题,首先找下规律:

首先想到是否存在循环,即经过多次洗牌后回到原状态的情况,但手玩了几组以后发现有循环但没有规律,只能知道循环节长度小于等于 \(n\) ,显然会 \(TLE\) ;
所以对于一些循环节较长的数据很容易被卡掉 (比如这组:9000000000 1 1
代码转载自 @Ishar-zdl

找循环节
#include<bits/stdc++.h>
#define int long long
using namespace std;
main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int n;cin>>n;int m,l;cin>>m>>l;
    int c=l,f=0;
    for(int i=1;i<=n;i++){
        l=(l+1)/2+(l%2)*n/2;
        if(l==c){f=i;break;}
    }
    f=m%f;
    for(int i=1;i<=f;i++)
    l=(l+1)/2+(l%2)*n/2;
    cout<<l;
}

然后自己推一下样例:
(以下每一行代表一次洗牌)

第一张 第二张 第三张 第四张 第五张 第六张
1 2 3 4 5 6
4 1 5 2 6 3
2 4 6 1 3 5
1 2 3 4 5 6

对 \(1\) 这张牌来说,位置变化是 \(1\) → \(2\) → \(4\) → \(1\)
\(1\) → \(2\) → \(4\) 可以很明显看出是 * 2 的变化
那 \(4\) → \(1\) 呢 ?
可以发现 \(1\) \(=\) \(4\) \(\times\) \(2\) \(-\) \(7\),也就是 \(1\) \(=\) \(4\) \(\times\) \(2\) \(mod\) \(7\)
所以得出结论:第 \(i\) 张牌最后的位置就是 \(i\) \(\times\) \(2^m\) \(mod\) \((n+1)\) 。

那么对于洗完牌后的第 \(l\) 张牌来说,它最初的位置就是 \(l\) \(\div\) \(2^m\) \(mod\) \((n+1)\) ;
所以我们只要求出 \(2^m\) 在 \(mod \ (n+1)\) 意义下的逆元即可。

于是打出代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,m,l,x55,y55,x,y;
ll exgcd(ll a,ll b,ll &x,ll &y){
	if(b==0){
		x=1;
		y=0;
		return a;
	}
	ll ret=exgcd(b,a%b,x,y);
	ll tmp=x;
	x=y;
	y=tmp-a/b*y;
	return ret;
}
ll qp(ll b,ll p,ll k){
	ll ans=1;
	b=b%k;
	while(p>0){
		if(p&1)ans=(ans*b)%k;
		p=p>>1;
		b=(b*b)%k;
	}
	return ans;
}
int main(){
	cin>>n>>m>>l;
	ll mod=n+1;
	ll t=qp(2,m,mod);
	exgcd(t,mod,x,y);
	x=(x%mod+mod)%mod;
	l=(l*x)%mod;
	cout<<l;
	return 0;
}

但是

image

又有人加测试点

简单思考一下可以发现,对于 \(1e10\) 的数据,快速幂中的 \(b \times b\) 在极限情况下可以达到 \(1e20\) , 是 \(long\) \(long\) 无法承受的 ;

那怎么办?

long long 不够用?__int128 拯救你!

__int128 可以,但这里要介绍的是另一种方法:

龟速乘!

也就是边乘边模,通过牺牲一些时间来避免乘法炸 \(long\) \(long\) 的方式,与快速幂很像

龟速乘
ll mul(ll b,ll p,ll k){//龟速乘
	ll ans=0;
	b=b%k;
	while(p>0){
		if(p&1)ans=(ans+b)%k;
		p>>=1;
		b=(b+b)%k;
	}
	return ans%k;
}
可以与快速幂对比记忆
ll qp(ll b,ll p,ll k){//快速幂
	ll ans=1;
	b=b%k;
	while(p>0){
		if(p&1)ans=(ans*b)%k;
		p=p>>1;
		b=(b*b)%k;
	}
	return ans;
}

所以改一改就可以过了。

完整代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,m,l,x,y;
ll exgcd(ll a,ll b,ll &x,ll &y){//扩展欧几里得求逆元,因为这题的模数 n+1 不一定是质数,但一定是奇数,即与 2^m 互质
	if(b==0){
		x=1;
		y=0;
		return a;
	}
	ll ret=exgcd(b,a%b,x,y);
	ll tmp=x;
	x=y;
	y=tmp-a/b*y;
	return ret;
}
ll mul(ll b,ll p,ll k){//龟速乘
	ll ans=0;
	b=b%k;
	while(p>0){
		if(p&1)ans=(ans+b)%k;
		p>>=1;
		b=(b+b)%k;
	}
	return ans%k;
}
ll qp(ll b,ll p,ll k){//快速幂
	ll ans=1;
	b=b%k;
	while(p>0){
		if(p&1)ans=mul(ans,b,k);//记得把这里改为龟速乘
		p>>=1;
		b=mul(b,b,k);//还有这里
	}
	return ans%k;
}
int main(){
	cin>>n>>m>>l;
	ll mod=n+1;
	ll t=qp(2,m,mod);// 2^m
	exgcd(t,mod,x,y);// 2^m 的逆元
	x=(x%mod+mod)%mod;
	l=mul(x,l,mod);//龟速乘
	cout<<l;
	return 0;
}

标签:AHOI2005,int,ll,洗牌,long,return,ans,SHUFFLE,mod
From: https://www.cnblogs.com/LBTL/p/18103931

相关文章

  • CF1392H ZS Shuffles Cards 题解
    题目传送门前置知识概率DP解法设\(f_{i}\)表示有\(i\)张数字牌没进入\(S\),即\(S\)中只有\(n-i\)张数字牌时的期望轮数,有\(f_{i}=\frac{i}{i+m}f_{i-1}+\frac{m}{i+m}(f_{i}+1)\),解得\(f_{i}=f_{i-1}+\frac{m}{i}\),边界为\(f_{0}=1\)。由于每一张数字牌在joke......
  • YoloV5、ShuffleNetV2、YoloV5-Lite网络概述
    前言前段时间需要在树莓派上部署一个深度学习环境,先试了YoloV5,fs基本才0.3,远远达不到要求,于是就尝试了一下轻量化网络,试过mobileNet系列+YoloV4,fps有所提升,大概能达到0.9左右,但还是比较慢,于是就发现了YoloV5-Lite这个轻量化网络,极大地加速了fps,基本能达到3左右,因此详细了解了......
  • 21. 实现洗牌逻辑
    洗牌方法洗牌的时候,会把弃牌堆清除,牌堆中的每张牌都会和随机的牌进行交换一共有两个地方会进行洗牌操作,第一个是初始化牌堆的时候第二个是抽牌堆为空的时候项目相关代码代码仓库:https://gitee.com/nbda1121440/DreamOfTheKingdom.git标签:20240305_1905......
  • net8 随机数类Random GetItems() 、Shuffle()方法
    1、在8中对随机数类Random提供了GetItems()方法,可以根据指定的数量在提供的一个集合中随机抽取数据项生成一个新的集合:ReadOnlySpan<string>colors=new[]{"Red","Green","Blue","Black"};string[]t1=Random.Shared.GetItems(colors,10);Console.WriteLine(......
  • 轻量化CNN网络 - ShuffleNet
    1.ShuffleNetV1论文:ShuffleNet:AnExtremelyEfficientConvolutionalNeuralNetworkforMobileDevices网址:https://arxiv.org/abs/1707.01083提出了``ChannelShuffle`的思想,在ShuffleUnit中全是GConv和DWConv。GConv虽然能够减少参数与计算量,但GConv中不同组之间信......
  • spark中的shuffle
    在Spark中,Shuffle是一个核心概念和步骤,它是数据分发的过程,需要消耗大量的资源和时间。Shuffle的主要功能是将分布在各个节点上的同一类数据汇集到某一个节点上进行计算,此过程有助于提高整体性能和吞吐量。同时,Shuffle作为连接Map阶段和Reduce阶段的桥梁,其性能受到磁盘和网......
  • Shuffle与Stage划分
    一:Shuffle   在宽依赖关系中,RDD会根据每条记录的key进行不同分区的数据聚集,数据聚集的过程称为Shuffle。例如,对一个RDD进行reduceByKey()操作,RDD中相同key的所有记录将进行聚合,而key相同的所有记录可能不在同一个分区中,甚至不在同一个节点上,但是该操作必须将这些记录聚集到......
  • 【题解】AtCoder agc065_a Shuffle and mod K
    传送门:https://atcoder.jp/contests/agc065/tasks/agc065_a 为了方便理解,我们把要求的东西乘一个$-1$,再把答案序列倒过来;也就是说,我们现在要求$min_{A'}^{A'为A的排列}(\sum_{i=1}^{N-1}((A_{i+1}-A_{i})$$mod$$K))$比较显然的是,如果我们确定了答案序列的第一个数是多......
  • [Codeforces] CF1733C Parity Shuffle Sorting
    题面翻译给定一个长度为\(n\)的数组,你可以对它进行不超过\(n\)次操作。对于每次操作:选择两个下标\(l,r\),满足\(1\leql<r\leqn\);若\(a_l+a_r\)为奇数,将\(a_r\)赋值为\(a_l\),否则将\(a_l\)赋值为\(a_r\)。求一种方案,使得操作后的数组单调不减(即\(a_1\leq......
  • spark的shuffle和mapreduce的shuffle的区别
    功能上,MR的shuffle和Spark的shuffle是没啥区别的,都是对Map端的数据进行分区,要么聚合排序,要么不聚合排序,然后Reduce端或者下一个调度阶段进行拉取数据,完成map端到reduce端的数据传输功能。方案上,有很大的区别,MR的shuffle是基于合并排序的思想,在数据进入reduce端之前,都会进行sor......