洛谷力扣
2680. 最大或值
问题:
观察到,要选找位数最高的数左移k位,才可能使或值最大
尝试通过两次循环而不是排序找出所有最高位元素。
时间复杂度从$O(nlogn)$到$O(n)$
随后,对取出的最高位元素各自尝试左移,找出最大答案。
时间复杂度约$O(nlogn)$
整体时间复杂度约为$O(nlogn)$
成功TLE
代码:
1 | class Solution { |
改进思路:
将逐个左移的操作压缩时间复杂度,先用O(n)时间复杂度处理前缀与后缀或数,以达到降低每次取或的时间复杂度
1 | class Solution { |
P1075 [NOIP 2012 普及组] 质因数分解
简单水题
关键在于其搜索分界点是sqrt(n)
但是不能在分界点右边找
在右边查找的时间复杂度为$O(n - n^{\frac{1}{2}})$,而在分界点左边的时间复杂度是$O(n^{\frac{1}{2}})$,在n较大时差别尤其明显
1 |
|
关闭输入同步流黑魔法
1 | std::ios::sync_with_stdio(0) |
素数筛
欧拉筛:CSDN欧拉筛与埃式筛参考博客
使用了bitset数组代替bool1
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
using namespace std;
bitset<100000010> noP;
// bool noP[100000010];
vector<int> primer;
int main(){
ios::sync_with_stdio(0);
int n,q;
cin>>n>>q;
for(int i=2;i<=n;i++){
if(noP[i]==0)
primer.push_back(i);
for(int len=primer.size(),j=0;j<len;j++){
if(primer[j]*i>n)//若i是素数,则相当于从i开始乘倍,i之前的倍数没必要乘,因为i之前的数全部都被它们或它们的质因数筛过了
break;
noP[primer[j]*i]=1;
}
}
for(int i=0;i<q;i++){
int a;
cin>>a;
cout<<primer[a-1]<<"\n";
}
return 0;
}
P1012 [NOIP 1998 提高组] 拼数
解题思路:
按照字典序排序,可以选出左位数字高的字符串,然后按顺序拼接即可。
原代码: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
using namespace std;
const int MAXN = 30;
int n;
string a[MAXN];
bool compare(const string& _a,const string& _b){
return _a>_b;
}
int main(){
cin>>n;
for(int i=0;i<n;i++){
int temp;
cin>>temp;
a[i] = to_string(temp);
}
sort(a,a+n,compare);
string res = "";
for(int i=0;i<n;i++){
res+=a[i];
}
cout<<res<<endl;
return 0;
}
得分:75分
原因:整数按字典序排序,虽然可以正确处理$64$排在$598$这种情况,但是并不能正确处理$32$与$321$的关系。
如果按字典序排序,那么$321$应该在$32$前面。但在本题之中,$321$与$32$之间的顺序关系应该是$32321$,因为$1$小于$3$
因此,不能比较字典序,因为那样会在前缀相同的情况下,把长的放到前面。
实际上,在前缀相同时,应该比较的是超出部分的第一位与另一个字符串的第一位,因此应该稍作修改比较函数
1 |
|
思维题:P1007 独木桥
本题关键:如何理解士兵的转向。
由于士兵相向之后必定转向,且转向无需耗费时间,因此可以认为,当他们开始行动时,就会不断转向转向转向,直到中间的相向对全部消除。
既然如此,最后的状态必然是: 左出口 < < < < < > > > > > > > > > 右出口 ,类似于这种结构,只需要针对士兵位置,特化出最长时间情况(全部同向)和最短时间情况(在中点左右分段)即可。
1 |
|