蜗牛の狂奔笔记
对于蜗牛来说,狂奔虽不代表极速,但展现的却是一种拼尽全力的姿态........
pku 3252
2009年10月29日 星期四
题目链接:
PKU 3252 Round Numbers
分类:排列组合+区间计数
题目分析与算法原型
这道题目总的来说不是太难,但是实现起来细节比较多,所以WA了好多次,大致思路是,给你的两个数,start和end ,分别求出1到start,以及1到end之间(包括start和end自身)的round number 的个数,然后两个相减一下,就差不多是要求的数,当然了还需判断一下start是不是也是round number是的话刚才减的结果还要加1。假设现在给你的数是a,那么求1到a之间的round number可以分两步来进行,先求出a在二进制下的位数m,然后求出1到m-1位的二进制数的round number的和(这个不难,只是排列组合的计算),第二步就是要加上,二进制位数为m但《=a的所有二进制数中round number的个数。其实可以这样考虑,设一个二进制数为101001100,那么从100000000到其之间的round number的数的个数可以这样考虑,从第二位开始左往右扫描,碰到为1的时候将其变为0,然后此位后的位数任意组合的数都肯定小于原来的数,枚举这个情况下(先记下当前0和1的个数,方便计算剩下的位数组合中round number的数目)的round number数目,然后继续扫描一直到最后。
PS:此题代码实现的有些繁琐,有待改进..........
Code:
1
#include
<
stdio.h
>
2
int
x[
35
];
3
int
cal(
int
m,
int
a)
4
{
5
int
i,j
=
1
,res
=
1
;
6
for
(i
=
m
-
1
;i
>=
m
-
a;i
--
)
7
{
8
res
*=
i;
9
res
/=
j;
10
j
++
;
11
}
12
return
res;
13
}
14
int
num(
int
m)
15
{
16
int
k,i,res
=
0
;
17
if
(m
%
2
==
0
)k
=
m
/
2
;
18
else
k
=
m
/
2
+
1
;
19
20
for
(i
=
k;i
<
m;i
++
)res
+=
cal(m,i);
21
return
res;
22
}
23
int
check(
int
n)
24
{
25
int
res
=
0
,i,num
=
0
,y[
35
];
26
int
nn
=
n;
27
while
(nn)
28
{
29
y[res
++
]
=
nn
%
2
;
30
nn
/=
2
;
31
}
32
for
(i
=
0
;i
<
res;i
++
)
33
if
(y[i]
==
0
)num
++
;
34
else
num
--
;
35
36
if
(num
>=
0
)
return
1
;
37
else
return
0
;
38
}
39
int
weishu(
int
n)
40
{
41
int
res
=
0
,y[
35
];
42
43
int
nn
=
n;
44
while
(nn)
45
{
46
y[res
++
]
=
nn
%
2
;
47
nn
/=
2
;
48
}
49
return
res;
50
}
51
int
jisuan(
int
n)
52
{
53
int
k,i,j,y[
35
],num
=
0
;
54
55
int
nn
=
n;
56
while
(nn)
57
{
58
y[num
++
]
=
nn
%
2
;
59
nn
/=
2
;
60
}
61
k
=
num
/
2
-
1
;
62
for
(i
=
0
;i
<=
k;i
++
)
63
{
64
int
t
=
y[i];
65
y[i]
=
y[num
-
1
-
i];
66
y[num
-
1
-
i]
=
t;
67
}
68
int
num1
=
1
,num0
=
0
,ss,kk,res
=
0
;
69
for
(i
=
1
;i
<
num;i
++
)
70
{
71
if
(y[i]
==
1
)
72
{
73
num0
++
;
74
ss
=
num
-
i
-
1
;
75
76
if
(ss
+
num1
-
num0
<
0
)kk
=
0
;
77
else
78
{
79
if
((ss
+
num1
-
num0)
%
2
==
0
)kk
=
(ss
+
num1
-
num0)
/
2
;
80
else
kk
=
(ss
+
num1
-
num0)
/
2
+
1
;
81
}
82
if
(kk
<
ss)
83
{
84
int
mm,q,ii;
85
for
(ii
=
kk;ii
<=
ss;ii
++
)
86
{
87
mm
=
1
;
88
if
(ii
==
0
)res
+=
1
;
89
else
90
{
91
q
=
1
;
92
for
(j
=
ss;j
>
ii;j
--
)
93
{
94
mm
*=
j;
95
mm
/=
q;
96
q
++
;
97
}
98
res
+=
mm;
99
}
100
}
101
}
102
else
if
(kk
==
ss)
103
{
104
res
+=
1
;
105
}
106
107
num0
--
;
108
num1
++
;
109
}
110
else
num0
++
;
111
112
if
(i
==
num
-
1
&&
num0
>=
num1)res
++
;
113
}
114
return
res;
115
}
116
int
main()
117
{
118
int
i,s,f;
119
x[
1
]
=
0
;
120
for
(i
=
2
;i
<=
33
;i
++
)x[i]
=
x[i
-
1
]
+
num(i);
121
while
(scanf(
"
%d%d
"
,
&
s,
&
f)
!=
EOF)
122
{
123
int
a
=
weishu(s),b
=
weishu(f),ans
=
0
,c,d;
124
c
=
jisuan(s);
125
c
+=
x[a
-
1
];
126
d
=
jisuan(f);
127
d
+=
x[b
-
1
];
128
ans
=
d
-
c;
129
if
(check(s))ans
++
;
130
printf(
"
%d\n
"
,ans);
131
}
132
return
0
;
133
}
134
posted on 2009-10-29 16:06
蜗牛也Coding
阅读(330)
评论(0)
编辑
收藏
引用
只有注册用户
登录
后才能发表评论。
【推荐】100%开源!大型工业跨平台软件C++源码提供,建模,组态!
网站导航:
博客园
IT新闻
BlogJava
知识库
博问
管理
Powered by:
C++博客
Copyright © 蜗牛也Coding
<
2010年9月
>
日
一
二
三
四
五
六
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1
2
3
4
5
6
7
8
9
导航
C++博客
首页
新随笔
联系
聚合
管理
统计
随笔 - 78
文章 - 0
评论 - 96
引用 - 0
常用链接
我的随笔
我的评论
我参与的随笔
留言簿
(8)
给我留言
查看公开留言
查看私人留言
随笔档案
(78)
2011年7月 (1)
2011年4月 (1)
2010年11月 (4)
2010年10月 (4)
2010年9月 (2)
2010年8月 (7)
2010年3月 (1)
2010年2月 (5)
2009年12月 (2)
2009年10月 (1)
2009年9月 (1)
2009年8月 (16)
2009年7月 (31)
2009年6月 (2)
搜索
积分与排名
积分 - 92679
排名 - 258
最新评论
1. re: 关于 OpenGl
太谢谢了。
--袁锋
2. re: 关于 OpenGl
太感谢!
--芙
3. re: 关于MAC系统win 7虚拟机不能上网的问题[未登录]
.vmx文件在哪里?
--a
4. re: MFC中如何将 CFormView放置到一个CDockablePane中
注释掉的创建部分,指针调用
为何不用友元类声明下,就可以用了的。CreateOne,有点绕。
感谢博主分享。
--ren
5. re: 关于 OpenGl
非常感谢~~
--无叶莲
阅读排行榜
1. pragma comment的使用(转)(17212)
2. MFC中如何将 CFormView放置到一个CDockablePane中(8223)
3. (转)关于OpenGL的安装(4831)
4. 关于 OpenGl(4426)
5. VC 界面窗口,静态分割后如何锁定分隔条或限制分隔条的移动范围(4299)
评论排行榜
1. 据说是来自chrome的代码里的一个模板(13)
2. 关于 OpenGl(10)
3. Visual Studio 历史简介(转)(6)
4. pku 1200(6)
5. VC 界面窗口,静态分割后如何锁定分隔条或限制分隔条的移动范围(5)