题目链接:http://wikioi.com/problem/1509/
分析:
首先,根据题意可以推断出,对于任意一个状态,达到全0状态的途径只有一条
由此,写出n=5的全排列:
步数 状态 1的位置
0 0 0 0 0 0
1 1 0 0 0 0 1
2 1 1 0 0 0 2 1
3 0 1 0 0 0 2
4 0 1 1 0 0 3 2
5 1 1 1 0 0 3 2 1
6 1 0 1 0 0 3 1
7 0 0 1 0 0 3
8 0 0 1 1 0 4 3
9 1 0 1 1 0 4 3 1 16 8 2
10 1 1 1 1 0 4 3 2 1 16 8 4 2
11 0 1 1 1 0 4 3 2 16 8 4
12 0 1 0 1 0 4 2 16 4
13 1 1 0 1 0 4 2 1 16 4 2
14 1 0 0 1 0 4 1 16 2
15 0 0 0 1 0 4 16
16 0 0 0 1 1 5 4
17 1 0 0 1 1 5 4 1
18 1 1 0 1 1 5 4 2 1
19 0 1 0 1 1 5 4 2
20 0 1 1 1 1 5 4 3 2
21 1 1 1 1 1 5 4 3 2 1
22 1 0 1 1 1 5 4 3 1
23 0 0 1 1 1 5 4 3
24 0 0 1 0 1 5 3
25 1 0 1 0 1 5 3 1
26 1 1 1 0 1 5 3 2 1
27 0 1 1 0 1 5 3 2
28 0 1 0 0 1 5 2
29 1 1 0 0 1 5 2 1
30 1 0 0 0 1 5 1
31 0 0 0 0 1 5
然后,随意选取9,10,11,12等几行作分析。
可以发现,
设 第 i 个 1 的位置为f[i],
则步数=2^f[i]-2^f[i-1]+2^f[i-2]+...
当有偶数个0的时候,答案减去1。
由此可得递推式,出解。
ps:由于数据较大,要用高精,而且要压位。
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int c[3000]; int wei,len=1,n,cc[3000];
int re[3000],a[1010],aa[3100];
void cheng(int jk)
{
wei=1;
cc[wei]=1;
for (int i=1;i<=jk;i++)
{
memset(c,0,sizeof(c));
for (int j=1;j<=wei;j++)
{
c[j]+=cc[j]*2;
c[j+1]+=c[j]/100000000;
c[j]%=100000000;
}
if (c[wei+1]!=0)
{
wei++;
while (c[wei]>=100000000)
{
wei++;
c[wei]+=c[wei-1]/100000000;
c[wei-1]%=100000000;
}
}
for (int ii=1;ii<=wei;ii++) cc[ii]=c[ii];
}
}
void jia()
{
if (len<wei) len=wei;
for (int i=1;i<=len+1;i++)
{
re[i]+=c[i];
if (re[i]>=100000000)
{
len++;
re[i+1]+=re[i]/100000000;
re[i]%=100000000;
}
}
return ;
}
void jian()
{
for (int i=1;i<=len;i++)
{
re[i]-=c[i];
if (re[i]<0)
{
re[i+1]--;
re[i]+=100000000;
}
}
return ;
}
void jiann()
{
int jg=1;
re[jg]--;
while (re[jg]<0)
{
re[jg+1]--;
re[jg]+=100000000;
}
return ;
}
int main()
{
freopen("lan.in","r",stdin);
freopen("lan.out","w",stdout);
scanf("%d",&n);
int ans=0;
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if (a[i]==1)
{
ans++;
aa[ans]=i;
}
}
for (int i=ans;i>=1;i--)
{
cheng(aa[i]);
if ((ans-i)%2==0)
jia();
else jian();
{
printf("%d",re[len]);
for (int i=len-1;i>=1;i--)
{
if (re[i]<10000000)
{
int jiji=10000000;
while (re[i]/jiji==0)
{
printf("0");
jiji/=10;
}
}
printf("%d",re[i]);
}
}
}
if (ans%2==1)
jiann();
len++;
while (re[len]==0) len--;
printf("%d",re[len]);
for (int i=len-1;i>=1;i--)
{
if (re[i]<10000000)
{
int jiji=10000000;
while (re[i]/jiji==0)
{
printf("0");
jiji/=10;
}
}
printf("%d",re[i]);
}
}