Atcoder utpc2012 K-ラッピング (立体几何/置换/类欧几里得算法)

Atcoder utpc2012 K-ラッピング (立体几何/置换/类欧几里得算法)

K - ラッピング (atcoder.jp)

卡在了最后一步转换上:

已知置换\(L,D\),为立方体左滚和下滚的置换。

求:

\[\prod _{i=1}^B L^{\lfloor \frac{iA}{B} \rfloor-\lfloor \frac{(i-1)A}{B} \rfloor} R \]

(假设\(\gcd(A,B)=1\))

众所周知,置换是有结合律而没有交换律的,所以拆开来显然不现实。

考虑\(L\)的次数,可以发现要么是$\lfloor A/B \rfloor \(要么是\)\lceil A/B \rceil $。

确切的说,第\(i\)\(L\)的次数\(P_i\)满足:

\[P_i=\lfloor A/B \rfloor+[(i-1)*A\mod B-i*A\mod B\geq B-A\mod B] \]

把它理解到一个值域是\([0,B-1]\)的数轴上的跳跃,其实只有\(B\mod A\)个值是上取整,其它都是下取整。这样我们只需要使用类欧就可以了。

/*
{
######################
#       Author       #
#        Gary        #
#        2021        #
######################
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
//inline int read(){
//    int x=0;
//    char ch=getchar();
//    while(ch<'0'||ch>'9'){
//        ch=getchar();
//    }
//    while(ch>='0'&&ch<='9'){
//        x=(x<<1)+(x<<3)+(ch^48);
//        ch=getchar();
//    }
//    return x;
//}
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
struct cube{
	int a[6];
	cube(){
		rep(i,6) a[i]=i;
	}
	bool operator == (cube oth){
		rep(i,6) if(a[i]!=oth.a[i]) return false;
		return true;
	}
	void lr(){
		int od=a[0];
		a[0]=a[3];
		a[3]=a[2];
		a[2]=a[1];
		a[1]=od;
	}
	void dr(){
		int od=a[0];
		a[0]=a[5];
		a[5]=a[2];
		a[2]=a[4];
		a[4]=od;
	}
	cube operator * (cube oth){
		cube ret;
		rep(i,6) ret.a[i]=oth.a[a[i]];
		return ret;
	}
	cube operator ^ (LL t){
		if(t==0){
			return cube();
		}
		cube ret=(*this)^(t>>1);
		ret=ret*ret;
		if(t&1) ret=ret*(*this);
		return ret;
	}
};
LL gcd(LL A,LL B){
	if(B==0) return A;
	return gcd(B,A%B);
}
cube gcd(LL A,LL B,cube x,cube y){
	if(B==0) return x;
	return gcd(B,A%B,(x^(A/B))*y,x);
}
int main(){
	LL A,B;
	scanf("%lld%lld",&A,&B);
	if(A==0||B==0){
		puts("4");
		return 0;
	}
	LL g=gcd(A,B);
	A/=g;
	B/=g;
	double a,b;
	a=A,b=B;
	double cnt=0;
	cube now;
	cube tot;
	cube L,R;
	L.lr();
	R.dr();
	tot=gcd(A,B,L,R);
	while(!(cube()==now)||cnt==0){
		cnt+=1.0;
		now=now*tot;
	}
	cnt*=sqrt(a*a+b*b);
	printf("%.20f\n",cnt);
	return 0;
}
posted @ 2021-03-16 23:39  WWW~~~  阅读(99)  评论(0编辑  收藏  举报