(一)>>
i & (1<<j)
1<<j
表示二进制表示的1
(即0001
)的所有位向左平移j
个单位后的数,如j=1
,则平移后的结果是0010
,此时得到数2
。若j=3
,平移后的结果是1000
,此时得到数8
。向左平移j
位,即表示将原来的数乘上2^j
。可以类比十进制,所有位左移j
位,相当于在后面添了j
个0
,即乘上10^j
,在二进制中,即乘上2^j
。
&
在此处表示按位与,即两个二进制表示的数,在对应位置上进行取并的操作,都为1
时取1
,否则取0
。如1010
(十进制的10)和0101
(十进制的5)进行按位与操作后,得到的是0000
(十进制的0)。
i & (1<<j)
则表示 i
和 1<<j
(即2^j
) 按位与后得到的数。1<<j
的二进制表示只有第j
个位置(从右往左数,从0开始)上的数是1
,其余位置上的数是0
,i
和1<<j
进行按位与操作时,i
的第j
个位置是1
就返回1<<j
(判断语句中即为true
),i
的第j
个位置是0
就返回0
(判断语句中即为false
)。
当i=0
时,任何j
都不满足。
当i=1
时,j=0
满足条件。
当i=2
时,j=1
满足条件。
当i=3
时,j=0,1
满足条件。
当i=4
时,j=2
满足条件。
当i=5
时,j=0,2
满足条件。
当i=6
时,j=1,2
满足条件。
当i=7
时,j=0,1,2
满足条件。
当i=8
时,j=3
满足条件。
...
当i=2^n-1
时,j=0,1,2,...,n-1
满足条件。
归纳一下,如果j
表示数组a
(长度为n
)的索引,循环结构如下,则表示依次选取数组a
的一个子数组进行操作,直到选到它本身。
1 & (i>>j)
1 & (i>>j)
相当于i
右移 j
位后,若为奇数则返回1
,若为偶数则返回0
。代码相当于:
let a = i/(2**j);
if (a % 2 == 0) {
return 0;
} else {
return 1;
}
若i>=0 && i < 2^n ,j>=0 && j<n
,具体地,
当i=0
时,任何j
都不满足。
当i=1
时,j=0
满足条件。
当i=2
时,j=1
时满足条件。
当i=3
时,j=0,1
时满足条件。
当i=4
时,j=2
时满足条件。
当i=5
时,j=0,2
时满足条件。
当i=6
时,j=1,2
时满足条件。
当i=7
时,j=0,1,2
时满足条件。
当i=8
时,j=3
时满足条件。
总结:用 i&(1<<j) 的方法可以得出来每位的1和0的取值。
可以通过以下代码段任意组合一个序列 就是说 0000 0001 0010 0011 ......就是1代表取这个元素0代表不取这个元素。
用1&(i<<j)可以知道该位上的是0还是1.
for(int i=0;i<(1<<n);i++)
{
for(int j=0;j<n;j++)
{
if((i&(1<<j)))
{
......;
}
}
}
例题:2044. 统计按位或能得到最大值的子集数目 - 力扣(LeetCode)
2>>
计算几何的一些简单代码
double my_tan(double x){
return tan(x*pii/180);
}
double my_sin(double x){
return sin(x*pii/180);
}
double my_cos(double x){
return cos(x*pii/180);
}
const double pii=acos(-1);
3>>循环同构串的最小表示法和最大表示法
如何理解字符串的最大、最小表示法 - 知乎 (zhihu.com)
【最小表示法】【字符串】_c++字符串的最小表示法_行码棋的博客-优快云博客
int i = 0, j = 1, k = 0;
while(i < n and j < n and k < n)
{
if(a[(i + k) % n] == a[(j + k) % n])
k++;
else
{
a[(i + k) % n] > a[(j + k) % n] ? i = i + k + 1 : j = j + k + 1;
if(i == j)
i++;
k = 0;
}
}
i = min(i, j);
#include<bits/stdc++.h>
using namespace std;
using ll = long long ;
void solve()
{
int n;
cin >> n;
vector<int> a(n + 1);
for(int i = 0; i < n; i++)
cin >> a[i];
int i = 0, j = 1, k = 0;
while(i < n and j < n and k < n)
{
if(a[(i + k) % n] == a[(j + k) % n])
k++;
else
{
a[(i + k) % n] > a[(j + k) % n] ? i = i + k + 1 : j = j + k + 1;
if(i == j)
i++;
k = 0;
}
}
i = min(i, j);
for(int x = 0; x < n; x++)
cout << a[(x + i) % n] << " \n"[x == n - 1];
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
// cin >> t;
t = 1;
while(t--)
solve();
return 0;
}
4>>字符串哈希:
能够直接解决的问题就是,判断一个字符串和另外一个字符串是否相等。由o(n)的复杂度,直接转变成了o(1)的复杂度。
预处理一下每个字符串的哈希值,然后就可以进行直接判断比较。
【算法学习】字符串哈希(Hash)_字符串hash_Mikchy的博客-优快云博客
5>>高斯消元法:
其实就是解一个方程组。
C++高斯消元详解_高斯消去法c++_ixRic的博客-优快云博客
6>>
得到一个字符串的字典序的下一个:
-
POJ 1146,UVA 146
方法一:
string a; while(cin>>a&&a!="#") { if(next_permutation(a.begin(),a.end())) { cout<<a<<endl; }
方法二:
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;int front,behind;
string a;bool find()
{
int len =a.length()-1;
while(len>0)
{
if(a[len-1] >= a[len])
{
}
else
{
front = len-1;
return true;
}
len--;
}
return false;
}void change()
{
int len =a.length()-1;
int min=200;while(len>front)
{
if(a[len]>a[front]&&(int)a[len]<min)
{
min=len;
}
len--;
}
char temp=a[min];
a[min]=a[front];
a[front]=temp;
}void sort()
{
int len = a.length();
int i,j;
char temp;for(i=front+1;i<len;i++)
{
for(j=i;j<len;j++)
{
if(a[i]>a[j])
{
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
}
}int main()
{
while(cin>>a&&a!="#")
{
if(find())
{
change();
sort();
cout<<a<<endl;
}
else
{
cout<<"No Successor"<<endl;
}
}
return 0;
}