这个东西啊 逆过程是一个辗转相减 然后随机化以下最后状态另一个数就好了
比赛的时候被windows的rand坑死 windows下RAND_MAX是32768
被dls教导似乎windows下random_shuffle也有问题?
要不是rand不出来 就拿到奖品了233
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<ctime>
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
int tot=0;
inline int Gcd(int a,int b){
return !b?a:(tot+=a/b,Gcd(b,a%b));
}
int len=0;
int lst[1005];
int main(){
int T,t,n;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(T);
while (T--){
read(n); int minv=1<<30,mink;
for (int i=1;i<=1000 && minv>60;i++){
tot=0;
if (Gcd(n,t=(long long)rand()*rand()%(n-1)+1)==1)
if (tot<minv)
minv=tot,mink=t;
}
int a=n,b=mink;
len=0;
while (!(a+b==1))
if (a>b)
lst[++len]=0,a-=b;
else
lst[++len]=1,b-=a;
if (a==0 && b==1)
for (int i=len;i;i--)
printf("%d",lst[i]);
else
for (int i=len;i;i--)
printf("%d",1-lst[i]);
printf("\n");
}
return 0;
}
比赛时瞎jb乱rand被坑 开始想玄学做法 于是想到了黄金分割
自己怎么想 那么点有道理 大部分没道理
吉丽是这么说的:http://hihocoder.com/discuss/question/4096
0.618就是黄金分割啊..最优情况下就是来回加这样步数最少,你算一下两个的比例就是0.618,所以就直接在这个附近找就可以了
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<ctime>
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
int tot=0;
inline int Gcd(int a,int b){
return !b?a:(tot+=a/b,Gcd(b,a%b));
}
const double ff=0.618;
int len=0;
int lst[1005];
int main(){
int T,t,n;
freopen("t.in","r",stdin);
freopen("t1.out","w",stdout);
read(T);
while (T--){
read(n); int minv=1<<30,mink;
if (n*ff<=1000){
for (int i=1;i<=n && minv>60;i++){
tot=0;
if (Gcd(n,i)==1)
if (tot<minv)
minv=tot,mink=i;
}
}else{
for (int i=1;i<=1000 && minv>60;i++){
tot=0;
if (Gcd(n,n*ff-500+i)==1)
if (tot<minv)
minv=tot,mink=n*ff-500+i;
}
}
int a=n,b=mink;
len=0;
while (!(a+b==1))
if (a>b)
lst[++len]=0,a-=b;
else
lst[++len]=1,b-=a;
if (a==0 && b==1)
for (int i=len;i;i--)
printf("%d",lst[i]);
else
for (int i=len;i;i--)
printf("%d",1-lst[i]);
printf("\n");
}
return 0;
}