异或运算(a^b)的应用
2n+1个数中,n个数都出现了两次,怎么找剩下那一个数?所有数进行异或运算即可。利用性质a^b^b=a。
转关于while循环中的~scanf():
可以经常在ACM代码中看到 while(~scanf("%d",&n)){ } 这样的代码,意思是在读到输入结尾时循环也结束。
一般在读到输入流结尾时,scanf返回的是EOF。
EOF是在头文件stdio.h中定义的常量,一般为-1。
-1 的原码是10000001,反码是1111110,补码是11111111。复习一下,正数的原码、反码、补码都是一样的;负数的原码是符号位为1,反码是(对原码)符号位不变、其余位取反,补码是(对原码)符号位不变、其余位取反、末位加1.
~EOF则是对EOF进行按位取反操作,则为00000000。所以while条件不满足,循环结束。
注意Windows中cmd里用Ctrl+Z代表回车。
转ACM基础——OJ上的Java代码提交规范
1、输入
Scanner cin = new Scanner(System.in);
while(cin.hasNext()){
int a = cin.nextInt();
int b = cin.nextInt();
}
2、类名
public class Main {}
其他Java注意事项见PTA中提交Java程序的一些套路
转C语言数组下标太大怎么办?
当需要数组分配很大的空间,且为局部变量时,有可能会出现执行出错的情况。
这是因为,对于每个进程/线程,栈空间大小是有限的,而局部变量的内存是在栈上分配的,如果局部变量过大,则会出现分配失败的情况。
要解决这个问题,有两种方式:
1 将数组定义为全局变量。
全局变量分配时,会分配在全局变量空间,不受栈空间大小影响。
这种方法的好处是,代码简单,只需要将定义从函数内移动到函数外即可,其它不需要改变。
缺点是,在程序运行全程均需要占用该部分内存,很多时候这是一种浪费。
2 使用动态内存空间。
通过malloc,calloc, zalloc等函数,可以分配动态内存空间。该空间会分配在堆上,同样不受栈空间的限制。
不过这种方法使用后,必须通过free函数调用释放空间。
该方法的好处是,用后释放,不继续占用。
缺点是,代码复杂,必须保存原始分配空间的首地址,并对其释放,否则会出现内存泄露。
C++ STL示例
vector
类似于Java的ArrayList,动态数组。
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int main()
{
vector<int>a;
for(int i=0;i<15;i++)
a.push_back(i);
for(int i=0;i<15;i++)
cout << a[i]<< endl;
return 0;
}
set
一个集合,内部是二叉搜索树(红黑树)。
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int main()
{
set<int>s;
for(int i=0;i<20;i++)
s.insert(i);
for(int i=0;i<20;i+=2)
s.erase(i);
if(s.find(10)!=s.end())cout<<"10 exsits."<<endl;
else cout<<"10 doesn't exsit."<<endl;
return 0;
}
map
map和set类似,但是map是使用映射来查找的。
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int main()
{
map<string,int>mp;
mp["wei"]=1112300120;
mp["li"]=1123400987;
mp["zhang"]=1134562734;
cout<<mp["wei"]<<endl;
cout<<mp["li"]<<endl;
cout<<mp["zhang"]<<endl;
if(mp.find("li")!=mp.end())cout<<"YES"<<endl;
else cout<<"NO"<<endl;
return 0;
}
stack&queue
栈和队列。
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int main()
{
stack<string>s;
s.push("first");
s.push("last");
cout<<s.top()<<endl;
s.pop();
cout<<s.size()<<endl;
cout<<s.top()<<endl;
cout<<""<<endl;
queue<string>q;
q.push("first");
q.push("last");
cout<<q.front()<<endl;
q.pop();
cout<<q.size()<<endl;
cout<<q.front()<<endl;
return 0;
}
priority_queue
优先队列,队列里的元素有了优先级,新来的元素要按照优先级插到它应有的位置。通常用来实现一个堆。
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int main()
{
priority_queue<int>q;
q.push(1);
q.push(2);
q.push(3);
cout<<q.top()<<endl;
q.pop();
cout<<q.top()<<endl;
q.pop();
cout<<q.top()<<endl;
cout<<""<<endl;
priority_queue<int,vector<int>,less<int> >q1;
q1.push(1);
q1.push(2);
q1.push(3);
cout<<q1.top()<<endl;
q1.pop();
cout<<q1.top()<<endl;
q1.pop();
cout<<q1.top()<<endl;
cout<<""<<endl;
priority_queue<int,vector<int>,greater<int> >q2;
q2.push(1);
q2.push(2);
q2.push(3);
cout<<q2.top()<<endl;
q2.pop();
cout<<q2.top()<<endl;
q2.pop();
cout<<q2.top()<<endl;
return 0;
}
迭代器
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int main()
{
set<int> s;
set<int>::iterator it;
for(int i=0;i<8;i++)
s.insert(i);
for(it=s.begin();it!=s.end();++it)cout<<*it<<endl;
return 0;
}