寒假集训被学校巨佬们震撼、苦心刷题,终于有空在天梯赛前把板题凑合整理一下,(赛前来波自我安慰)
二分
hdu 2199
wa了两次,第二次再做时没有审清题,题目锁定了答案在0到100之间,其余的输出为No solution!,然而默认只有小于零才输出。(还有注意数据类型:double)
AC代码
#include<iostream>
#include<cmath>
#include<iomanip>
#include <cstring>
#define ll long long
using namespace std;
int nstd;
double compute(double x){
return 8*pow(x,4)+7*pow(x,3)+2*pow(x,2)+3*x+6;
}
int main(int argc, char const *argv[])
{
int T;
cin>>T;
while(T--){
int tem;
cin>>nstd;
double left=0,mid,right=100;
if (compute(left)<=nstd&&compute(right)>=nstd)
{
while(right-left>1e-10){
mid = (left+right)*1.0/2;
if (compute(mid)<nstd)
{
left=mid;
}
else right=mid;
}
cout<<fixed<<setprecision(4)<<left<<endl;
}
else cout<<"No solution!"<<endl;
}
return 0;
}
递归
CSU 2059
平面切割问题:我的思路,推导递推公式(如果TLE就开数组然后递推填数组),通过考虑极端情况,即让"V型字"或"Z型字"延伸到边界,但实际上是延伸不到边界,因此每次要减去相应的值。
主要是在最后的输出处有每次特殊情况减去的操作。
#include<iostream>
using namespace std;
long long int d(int a){
if (a==1)
{
return 4;
}
else{
return d(a-1)+9*a-6;
}
}
int main(int argc, char const *argv[])
{
int T;
cin>>T;
while(T--)
{
int p;
cin>>p;
cout<<d(p)-2*p<<endl;
}
return 0;
}
并查集
hdu1213
并查集问题(有向)的关键在于两个函数,第一个可以理解为找到父节点的函数,第二个为融合(即merge函数),将有关联的两个元素联系起来。
这道题第二遍做的时候wa了一次,对比了集训时第一遍做的错在了merge函数的融合部分,即如果两者的父节点不同的时候应该把另一个元素的父节点接到列一个元素的父节点后边,不是把另一个元素接到另一个元素的父节点后边(因为这样可以避免另一个父节点是自己的情况)。
#include<iostream>
using namespace std;
int fa[1050];
int findfa(int x){
if (fa[x]!=x)
{
fa[x]=findfa(fa[x]); //如果自己的父节点不是自己=>就顺着树枝往前找
}
return fa[x];
}
void merge(int x,int y){
int temfax=findfa(x);
int temfay=findfa(y);
if (temfax!=temfay)
{
fa[temfay]=temfax; //如果两个的父节点不是一个=>就将后者的父节点转为前者的父节点
}
return;
}
int main(int argc, char const *argv[])
{
int T;
cin>>T;
while(T--){
int m,n;
cin>>m>>n;
for (int i = 1; i <= m; ++i) //初始化fa数组
{
fa[i]=i;
}
int s,t;
for (int i = 0; i < n; ++i)
{
cin>>s>>t;
merge(s,t);
}
int ans=0;
for (int i = 1; i <= m; ++i)
{
if (fa[i]==i)
{
ans++;
}
}
cout<<ans<<endl;
}
return 0;
}