今天的四道题相比昨天的四道明显感觉难了好多,作满三小时也没有AK,(实际考试的时候是肯定不会给你三个小时来做题的) 不过好消息是找到了两个思维漏洞,也算是有所收获吧。(程序员的自我安慰ing
1.PAT1104 连续子列和
题目大意:给出一个数列,求出这个数列的所有连续子列的元素之和。
思路:这个题属于典型的会者不难,难者不会类型的题目。找出规律 i*(N-i+1)来就非常简单,13行代码就可以搞定(我当时写得复杂了)。假如没有看出什么规律 即使用DP也会超时,所以遇到类似的问题(PAT1049数1的个数,数量级也是很大)先找找有没有规律,没有找到的话,再想其他的,好在都是暴力可以解的,至少能得一部分分。
注意点:一刷的时候没有发现的一个问题,二刷终于暴露出来了,一刷的时候写的是sum+=num[i]*(i)*(N+1-i);
而二刷的时候一开始写的是sum+=(i)*(N+1-i)&num[i];
当时虽然也考虑过数组越界问题,但是脑子一短路想成把int的上界当成2 *10^10了后来才意识到上界是 2 *10^9 。(话说现在真想抽自己两下) 所以后面一种写法正好回导致整形的越界,这点一定要注意!!
代码:
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
const int maxn=100010;
int N;
double num[maxn];
int main(){
cin>>N;
for(int i=1;i<=N;i++){
scanf("%lf",&num[i]);
}
double sum=0;
for(int i=1;i<=N;i++){
sum+=num[i]*(i)*(N+1-i);
}
printf("%.2lf",sum);
}
- PAT1105 螺旋序列
题目大意:给出一个N长度大小的数组,填充成一个螺旋序列
思路:纯模拟的题,中间有一个大小符号写反了,找了半小时bug。。还是要训练自己找bug的能力啊啊啊,现在想来还是每次填充完就直接输出比较合适。
代码:
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
const int maxn=10010;
int N;
int A,B;
vector<int> v[maxn];
void getAB(int N){
for(int i=1;i*i<=N;i++){
if(N%i==0) B=i;
}
A=N/B;
}
bool cmp(int a,int b){
return a>b;
}
int num[maxn];
int main(){
scanf("%d",&N);
getAB(N);
//cout<<A<<B<<endl;
for(int i=1;i<=A;i++){
v[i].resize(B+1);
}
for(int i=0;i<N;i++){
scanf("%d",&num[i]);
}
sort(num,num+N,cmp);
int index=0;
int ed=0;
while(1){
for(int i=1+ed;i<=B-ed;i++){
v[1+ed][i]=num[index++];if(index==N) break;
}
//cout<<index<<endl;
//cout<<1+ed<<" "<<B-ed<<endl;
if(index==N) break;
for(int i=2+ed;i<A-ed;i++){
v[i][B-ed]=num[index++];if(index==N) break;
}
//cout<<index<<endl;
//cout<<2+ed<<" "<<A-ed<<endl;
if(index==N) break;
for(int i=B-ed;i>=ed+1;i--){
v[A-ed][i]=num[index++];if(index==N) break;
}
//cout<<index<<endl;
//cout<<B-ed<<" "<<ed+1<<endl;
if(index==N) break;
for(int i=A-1-ed;i>=ed+2;i--){
v[i][1+ed]=num[index++];if(index==N) break;
}
//cout<<index<<endl;
//cout<<A-1-ed<<" "<<ed+1<<endl;
if(index==N) break;
ed++;
}
for(int i=1;i<=A;i++){
for(int j=1;j<=B;j++){
cout<<v[i][j];
if(j!=B) cout<<" ";
}
cout<<endl;
}
return 0;
}
- PAT1106 供应商最小价格
题目大意:给出一个树,求出所有的叶节点最小的层数和最小层数的叶节点数量
思路:建树再遍历每个节点赋予层值。 有一点二重循环的时候两个循环节都写成了i 。不过幸好这个bug比较好找。
代码:
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;
const int maxn=100010;
int N;
double p,r;
struct Node{
int layer;
vector<int> child;
}node[maxn];
void get(int root,int layer){
node[root].layer=layer;
for(int i=0;i<node[root].child.size();i++){
get(node[root].child[i],layer+1);
}
}
int main(){
scanf("%d %lf %lf",&N,&p,&r);
for(int i=0;i<N;i++){
int temp;scanf("%d",&temp);
for(int j=0;j<temp;j++){
int num;scanf("%d",&num);
node[i].child.push_back(num);
}
}
get(0,0);
//for(int i=0;i<N;i++) cout<<node[i].layer<<" ";cout<<endl;
int maxlay=0x3ffffff,ans=0;
for(int i=0;i<N;i++){
if(node[i].child.size()==0){
if(node[i].layer<maxlay) {maxlay=node[i].layer;ans=1;}
else if(node[i].layer==maxlay) ans++;
}
}
//cout<<maxlay<<endl;
printf("%.4lf %d",pow(double(1+0.01*r),double(maxlay))*p,ans);
}
- PAT1107 兴趣聚类
题目大意:给出N个人的兴趣,依据兴趣进行聚类,输出同类的个数和同类各个人的数量。
思路: 并查集,可以不进行路径压缩。同时要注意的是这里是根据兴趣进行合并运算,但是统计的是人的数量。因此需要把兴趣看成这个人的某种属性,合并运算后,再进行一次遍历,按照不同的集合,把人进行归类。最后输出。
注意点:由于好久没写并查集了,重新写代码的过程中犯了一个典型的错误。
void Union(int a,int b){
int A=getfa(a);
int B=getfa(b);
if(A!=B) father[B]=A;
}
注意合并集合都是根据父节点进行操作的,所以这里应该把父节点之间进行合并,而不是father[b] = a
,这点十分关键。
代码:
#include <algorithm>
#include <vector>
#include <iostream>
#include <unordered_map>
using namespace std;
const int maxn=10010;
int father[maxn],N;
vector<int> stu[maxn];
unordered_map<int,int> m;
void re(){
for(int i=0;i<maxn;i++) father[i]=i;
}
int getfa(int x){
int a=x;
while(x!=father[x]){x=father[x];}
while(a!=x){
int s=father[a];
father[a]=x;
a=s;
}
return x;
}
bool cmp(int a,int b){return a>b;}
void Union(int a,int b){
int A=getfa(a);
int B=getfa(b);
if(A!=B) father[B]=A;
}
int main(){
re();
int N;scanf("%d",&N);
for(int i=0;i<N;i++){
int size,fa;scanf("%d: %d",&size,&fa);
stu[i].push_back(fa);
for(int j=1;j<size;j++){
int temp;scanf("%d",&temp);
stu[i].push_back(temp);
Union(fa,temp);
}
}
for(int i=0;i<N;i++){
int x=getfa(stu[i][0]);
if(m.find(x)==m.end()){
m[x]=1;
}
else m[x]++;
}
cout<<m.size()<<endl;
vector<int> ans;
for(auto it=m.begin();it!=m.end();it++){
ans.push_back(it->second);
}
sort(ans.begin(),ans.end(),cmp);
for(int i=0;i<ans.size();i++){
printf("%d",ans[i]);if(i!=ans.size()-1)cout<<" ";
}
}
总之还是任重而道远,与bug的竞争还有很长的一段路要走。