连环锁
Description
许多人一定很熟悉九连环(如下图),九个环被串在一起,操作规则如下:第一个(右边)环可以任意装卸,如果第k个环没有被卸掉,而第k个环前边(右边)的所有环都被卸掉,则第k+1个环(第k个环左边的环)可以任意装卸(如果存在的话)。
用0表示此换被卸掉,1表示此环没有被卸掉,则九连环的每个状态可以用一个长度为9的二进制串来表示,如:111111001经过一次操作可以变成111111000,也可以变成111111011,111111111经过一次操作可以变成111111110,也可以变成111111101。 任务描述: 你现在要操作的是一个n连环,n为正整数,给出n连环的两种状态,计算出从第一种状态变换到第二种状态所需要的最少步数。 Input
第一行是一个正整数m,表示有m组测试数据。
每组测试数据一共3行,第一行是一个正整数n (0 < n < 128),后两行每一行描述一种状态,n个数(0或1),用空格隔开。 Output
对于每一组测试数据输出一行,一个非负整数,表示从第一种状态变换到第二种状态所需要的最少步数。
Sample Input 2 3 0 0 0 1 0 0 4 1 0 0 0 0 1 1 0 Sample Output 7 11 Source |
Position
http://poj.org/problem?id=1832
Solution
看下这道题基本就会做了,一个状态到另一个状态=(一个状态→ 0)-(一个状态→0),加些高精度减法,与比大小即可
Code
// This file is made by YJinpeng,created by XuYike's black technology automatically. // Copyright (C) 2016 ChangJun High School, Inc. // I don't know what this program is. #include <iostream> #include <vector> #include <algorithm> #include <cstring> #include <cstdio> #include <cstdlib> #include <cmath> #define MOD 1000000007 #define INF 1e9 using namespace std; typedef long long LL; const int MAXN=1010; inline int max(int &x,int &y) {return x>y?x:y;} inline int min(int &x,int &y) {return x<y?x:y;} inline int gi() { register int w=0,q=0;register char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')q=1,ch=getchar(); while(ch>='0'&&ch<='9')w=w*10+ch-'0',ch=getchar(); return q?-w:w; } const int __bmod__=100000; struct BN{ int a[100]; BN(){memset(a,0,sizeof(a));} int& operator [](int n){return a[n];} void get(int n){ memset(a,0,sizeof(a)); a[1]=n;if(a[1])a[0]=1; while(a[a[0]+1]){a[a[0]+1]=a[a[0]]/__bmod__;a[a[0]++]%=__bmod__;} } bool operator <(BN b) const{ if(a[0]<b[0])return 1; if(a[0]>b[0])return 0; for(int i=a[0];i>=1;i--){ if(a[i]>b[i])return 0; if(a[i]<b[i])return 1; } return 0; } BN operator -(BN b) const{ BN ans=*this;int q=1; if(ans<b)swap(ans,b),q=-1; for(int i=1;i<=ans[0];i++){ ans[i]=ans[i]-b[i]; if(ans[i]<0){ans[i+1]--;ans[i]+=__bmod__;} } while(ans[0]&&!ans[ans[0]])ans[0]--; for(int i=1;i<=ans[0];i++)ans[i]*=q; return ans; } BN operator +(BN b) const{ b[0]=max(a[0],b[0]); for(int i=1;i<=b[0];i++){ b[i]+=a[i]; if(b[i]>=__bmod__){b[i+1]+=b[i]/__bmod__;b[i]%=__bmod__;} } if(b[b[0]+1])b[0]++; return b; } BN operator *(BN b) const{ BN ans; ans[0]=a[0]+b[0]-1; for(int i=1;i<=a[0];i++) for(int o=1;o<=b[0];o++){ int now=i+o-1; ans[now]+=a[i]*b[o]; } for(int i=1;i<=ans[0];i++)if(ans[i]>=__bmod__){ans[i+1]+=ans[i]/__bmod__;ans[i]%=__bmod__;} if(ans[ans[0]+1])ans[0]++; return ans; } void print(){printf("%d",a[a[0]]);for(int i=a[0]-1;i>=1;i--)printf("%.5d",a[i]);printf("\n");} }now,f[2],o,t,up,mu; int a[MAXN]; int main() { freopen("1832.in","r",stdin); freopen("1832.out","w",stdout); int T=gi(); while(T--){ int n=gi(); for(int x=0;x<2;x++){ for(int i=n;i>=1;i--)a[i]=gi(); f[x].get(a[1]),o.get(1-a[1]),t.get(1),up.get(1),mu.get(2); for(int i=2;i<=n;i++){ if(a[i]) now=f[x],f[x]=o+t+up,o=now; else o=o+t+up; t=t*mu+up; } } if(f[0]<f[1]) (f[1]-f[0]).print(); else (f[0]-f[1]).print(); } return 0; }