zoukankan      html  css  js  c++  java
  • LA3510 Pixel Shuffle

    题意

    PDF

    分析

    思路挺简单的,题目中的每个命令(包括命令的逆)相当于一个置换。

    (O(n^2k))的时间复杂度从右往左求出这些置换的乘积A,然后求m使Am = I(I为全等置换)

    还是先把A分解循环,m则等于所有循环节长度的最小公倍数。

    代码

    #include<bits/stdc++.h>
    #define rg register
    #define il inline
    #define co const
    template<class T>il T read(){
        rg T data=0,w=1;rg char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') w=-1;ch=getchar();}
        while(isdigit(ch)) data=data*10+ch-'0',ch=getchar();
        return data*w;
    }
    template<class T>il T read(rg T&x) {return x=read<T>();}
    typedef long long ll;
    using namespace std;
    
    int gcd(int a,int b) {return b?gcd(b,a%b):a;}
    int lcm(int a,int b) {return a/gcd(a,b)*b;}
    #define ID(i,j) ((i)*n+(j))
    int newpos(int n,int i,int j,co char*op){
    	if(op[0]=='r') return ID(n-1-j,i); // rot
    	if(op[0]=='s') return ID(i,n-1-j); // sym
    	if(op[0]=='b'&&op[1]=='h') // bhsym
    		return i<n/2?ID(i,j):ID(i,n-1-j);
    	if(op[0]=='b'&&op[1]=='v') // bvsym
    		return i<n/2?ID(i,j):ID(n/2+n-i-1,j);
    	if(op[0]=='d')
    		return i%2==0?ID(i/2,j):ID(n/2+i/2,j);
    	if(op[0]=='m'){
    		int k=i/2;
    		if(j<n/2)
    			return i%2==0?ID(2*k,2*j):ID(2*k,2*j+1);
    		else
    			return i%2==0?ID(2*k+1,2*(j-n/2)):ID(2*k+1,2*(j-n/2)+1);
    	}
    	return assert(op[0]=='i'),ID(i,j);
    }
    
    co int N=1024;
    int orig[N*N];
    void apply(int*image,int n,co char*op){
    	bool inv=op[strlen(op)-1]=='-';
    	copy(image,image+n*n,orig);
    	for(int i=0;i<n;++i)for(int j=0;j<n;++j){
    		int p=ID(i,j),p2=newpos(n,i,j,op);
    		if(!inv) image[p2]=orig[p];
    		else image[p]=orig[p2];
    	}
    }
    
    int vis[N*N];
    int solve(int*p,int n){
    	fill(vis,vis+n,0);
    	int ans=1;
    	for(int i=0,j,len;i<n;++i)if(!vis[i]){
    		j=i,len=0;
    		do vis[j]=1,j=p[j],++len;
    		while(j!=i);
    		ans=lcm(ans,len);
    	}
    	return ans;
    }
    
    int cur[N*N];
    int main(){
    //	freopen(".in","r",stdin),freopen(".out","w",stdout);
    	int T,n,n2;
    	read(T),read(n);
    	for(;T--;n=n2){
    		for(int i=0;i<n*n;++i) cur[i]=i;
    		vector<string> ops;
    		for(int i=0;;++i){
    			static char op[10];
    			if(scanf("%s",op)==EOF) break;
    			if(isdigit(op[0])) {sscanf(op,"%d",&n2);break;}
    			ops.push_back(op);
    		}
    		for(int i=ops.size()-1;i>=0;--i)
    			apply(cur,n,ops[i].c_str());
    		printf("%d
    ",solve(cur,n*n));
    		if(T) puts("");
    	}
    	return 0;
    }
    
  • 相关阅读:
    Java实现 蓝桥杯 历届试题 连号区间数
    Java实现 蓝桥杯 历届试题 连号区间数
    Java实现 蓝桥杯 历届试题 连号区间数
    Java实现 蓝桥杯 历届试题 连号区间数
    Java实现 蓝桥杯 历届试题 连号区间数
    Java实现 蓝桥杯 历届试题 大臣的旅费
    Java实现 蓝桥杯 历届试题 大臣的旅费
    Java实现 蓝桥杯 历届试题 大臣的旅费
    Java实现 蓝桥杯 历届试题 大臣的旅费
    Navicat查询哪些表有指定字段名
  • 原文地址:https://www.cnblogs.com/autoint/p/10641962.html
Copyright © 2011-2022 走看看