图片中题目的代码中位运算的部分不理解。
void main()
{
int match;
int n;
scanf("%d", &n);
int count = 0;
for (int i = 0; i < (1 << n); i ++)
{
match = 0;
for (int j = 0; j <= n - 3; j++)
{
if (((i & (7 << j)) ^ (5 << j)) == 0) // bin(7)=111; bin(5)=101
{
match = 1;
break;
}
}
if (match == 0)
count ++;
}
if (((i & (7 << j)) ^ (5 << j)) == 0) 这部分^(5<<j)这个我是理解的,比较各个位置的101.但是前面i&(7<<j)这部分猜想是2^n个10组合,但是不理解是如何得出的,在纸上硬算发现也不对头。求解答
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
使用
7<<j
保留有效的3个检查位(循环,一位一位检查),如果有则(i & (7 << j)
为<n-3-j个0>101<j个0>
,举个例子:n=7, i=44, j=3的场景:
提供一个更侧重数学分析的思路,可缩短运行时间至O(lg n)。记fx(n) = 长度为n的01串个数,且这些01串(1)不含101;(2)结尾为x,x=(00,01,10,11)。通过观察可以得到递推关系:
f0(n+1) = f0(n) + f2(n)
f1(n+1) = f0(n)
f2(n+1) = f1(n) + f3(n)
f3(n+1) = f1(n) + f3(n)
因此从初始值
f(2) = (f0(2), f1(2), f2(2), f3(2))' = (1, 1, 1, 1)'
通过计算矩阵乘方可以推出:
f(n) = M^(n-2) * f(2)
其中
耗时集中在计算M^n。用递归可以节省大量时间,比如计算M^8 = M^2^2^2,即复杂度为O(lg n)。
还可以进一步将M对角化,得到一个复对角矩阵。如果编程语言或库函数支持复数的话,甚至可将复杂度降低到O(1)。
7的二进制为
111
5的二进制为
101
(i&(7<<j))
是找到i的第j位到第j+1位上的01情况5<<j
是找到5左移j位后的01情况(i&(7<<j))^(5<<j)
是判断i的第j位到第j+1位是不是101