题意:给一个初始值1,每步操作将1替换为01,将0替换为10。问N步操作后有多少对连续的0。
解法:f[i]表示第i步后的答案。可以直接打表发现规律——奇数步后,f[i]=f[i-1]*2-1;偶数步后,f[i]=f[i-1]*2+1;
至于原因——我只能简单说一点。第i步后的答案可由i-1步后的“01”+“1”+“0”的个数推出,而“01”*2+“1”+“0”=01串的总个数。用x表示i-1步后的“01”的个数,则f[i]=x+(2^(i-1)-x*2);但这样复杂度挺高,我也不知道怎么优化了。
noi oj上的实际数据没有1000这么大,在65以内,用long long也可以过。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 #define N 1010 7 8 int n; 9 long long f[N]; 10 11 int main() 12 { 13 f[1]=0; 14 for (int i=2;i<=N;i++) 15 { 16 if (i%2) f[i]=f[i-1]*2-1; 17 else f[i]=f[i-1]*2+1; 18 } 19 while(~scanf("%d",&n)) printf("%lld ",f[n]); 20 return 0; 21 }
我高精度的不知为何在noi oj上AC,在poj上WA。若有大牛能纠正我,请多多指教~
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 #define N 1000 7 8 struct node 9 { 10 int s[210]; 11 int l; 12 node() {l=0;memset(s,0,sizeof(s));} 13 }; 14 node f[N+10]; 15 16 node operator*(node x,int y)//不可省掉构成运算符左右的整型 17 { 18 node z; 19 z.l=x.l; 20 for (int i=1;i<=z.l;i++) 21 { 22 z.s[i]+=x.s[i]*2; 23 if (z.s[i]>9) z.s[i+1]+=z.s[i]/10,z.s[i]%=10; 24 } 25 while (z.s[z.l+1]) z.l++; 26 return z; 27 } 28 node operator-(node x,int y) 29 { 30 node z=x; 31 int t=1; 32 z.s[t]--; 33 while (z.s[t]<0) z.s[t]+=10,z.s[++t]--; 34 while (!z.s[z.l]) z.l--; 35 return z; 36 } 37 node operator+(node x,int y) 38 { 39 node z=x; 40 int t=1; 41 z.s[t]++; 42 while (z.s[t]>9) z.s[t+1]+=z.s[t]/10,z.s[t++]%=10; 43 while (z.s[z.l+1]) z.l++; 44 return z; 45 } 46 void print(node x) 47 { 48 for (int i=x.l;i>=1;i--) 49 printf("%d",x.s[i]); 50 printf(" "); 51 } 52 int main() 53 { 54 freopen("a.in","r",stdin); 55 freopen("a.out","w",stdout); 56 f[1].l=1,f[1].s[1]=0; 57 for (int i=2;i<=N;i++) 58 { 59 if (i%2) f[i]=f[i-1]*2-1; 60 else f[i]=f[i-1]*2+1; 61 } 62 int n; 63 while(~scanf("%d",&n)) print(f[n]); 64 return 0; 65 }
P.S.重载运算符 不可省掉构成运算符左右的2个类型,例如:整型。