PAT 错题集

1:筛素数,主要是格式问题

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=110005;
int prime[N];
int pri_n=0;
int mark[N];
void find_prime() {
	for(int i=2; i<=N; i++) {
		if(mark[i]) continue;
		prime[pri_n++]=i;
//		cout<<i<<' ';
		if(i>10000) continue;
		for(long long j=i*i; j<=N; j+=i)
			mark[j]=1;
	}
}
int main() {
	int a,b;
	memset(mark,0,sizeof(mark));
	find_prime();
//	cout<<pri_n;
	scanf("%d%d", &a,&b);
	for(int i=a,j=1; i<=b; i++,j++) {
		if(j%10==0) {
			j=0;
			printf("%d\n", prime[i-1]);
		}
		else if(i==b) printf("%d", prime[i-1]);
		else printf("%d ", prime[i-1]);
	}
	return 0;
}

2:1014 福尔摩斯的约会,模拟题由4行字符串得出week、hour、minute,关键是读懂题意!要加快读题速度,可以参考样例快速理解,但是需要意识到样例很可能具有混淆视听的“作用”。这里需要注意的是,我利用了n来控制读的顺序,因为必须是读完week后再读hour,(这里还需要注意If else的问题,我刚开始两个if导致读完week和hour读的一样)

#include<iostream>
using namespace std;
string week[7]= {"MON","TUE","WED","THU","FRI","SAT","SUN"};

int main () {//17:03->17:53 
	string a,b;
	cin>>a>>b;
	int k=min(a.length(), b.length());
	int n=0;//用于控制读的次序 
	string w;
	int hour,minute;
	for(int i=0; n<2&&i<k ; i++) {
		if(n==0 && a[i]==b[i] && a[i]<='G'&&a[i]>='A') {
			w=week[a[i]-'A'];//A就是Monday
			n++;
		} 
		//要写else,不然n++后,下面这个条件也成绩了 
		else if(n==1 && a[i]==b[i] && (a[i]<='9'&&a[i]>='0'||a[i]<='N'&&a[i]>='A')) {
			if(a[i]<='9'&&a[i]>='0') hour=a[i]-'0';
			else hour=a[i]-'A'+10;
			break;
		}
	}
	cin>>a>>b;
	k=min(a.length(), b.length());
	for(int i=0; ; i++) {
		if(a[i]==b[i] && (a[i]<='Z'&&a[i]>='A'||a[i]<='z'&&a[i]>='a')) {
			minute=i;//A就是Monday
			break;
		}
	}
	printf("%s %02d:%02d", w.c_str(),hour,minute);
	return 0;
}

3.吃糖果 不是PAT,抽屉原理or排列原理?反正感觉不错,另一个解析

4.1005 继续(3n+1)猜想 问是不是“覆盖数”,题目理解耗了时间,另外PAT题目确实很多坑:

  • 数组开多少其实是无法直接知道的,因为不知道给的数会不会一直3n+1下去?注意偶数/2后会变奇数,所以可能越来越大,这里数组开到2000才不会段错误
  • “从大到小”输出,因为样例给的默认升序,误导我直接倒序输出,其实需要排序的
    • 而我用的set,不能迭代器不能直接+-,要用it++或it--来更新,倒序输出的话,直接在判断的里面用*--it!=se.begin()即可
  • 控制末尾没有空格的另一个方法(有时候不是按照顺序,也就无法先输出n-1,再输出last one,so新get一好方法)
#include<iostream>
#include<cstring>
#include<set>
using namespace std;
const int N=2005;
const int INF=0x7fffffff;
int a[N],vis[N];
set<int>se;
set<int>::iterator it;

int main() {
	int n;
	cin>>n;
	memset(vis,0,sizeof(vis));
	se.clear();
	for(int i=0; i<n; i++) {
		scanf("%d", &a[i]);
		int t=a[i];
		while(t!=1) {
			if(t&1) { //奇数
				t=(3*t+1)>>1;
				vis[t]=1;
			} else {
				t>>=1;
				vis[t]=1;
			}
		}
	}
	for(int i=0; i<n; i++) {
		if(vis[a[i]]==0) {
			se.insert(a[i]);
		}
	}
	int j=0;
	for(it=se.end(); it!=se.begin(); ) {
		if(!j) {
			printf("%d", *--it);
			j=1;
		} else printf(" %d", *--it);
	}
	return 0;
}

5.1002 A+B for Polynomials,多项式加法,理解题意后不难,注意

  • 不能cin>>k>>a[k] 然后读k后放a[k]里,要分开写
  • 多项式的系数...没有限制,别被高精度的思维局限了(很可笑)
  • 注意可能有0项的问题,特判不能带空格
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int N=1005;
const int INF=0x7fffffff;
double a[N],b[N];
int main() {//理解完题意20:45->21:16
	int an,bn,k,ma=-INF;	
	memset(a,0,sizeof(a));
	memset(b,0,sizeof(b));
	cin>>an;
	for(int i=0; i<an; i++) {
		scanf("%d", &k);//不能直接写cin>>k>>a[k]; 
		scanf("%lf", &a[k]);
		if(k>ma) ma=k;
	}
	cin>>bn;
	for(int i=0; i<bn; i++) {
		scanf("%d", &k);
		scanf("%lf", &b[k]);
		if(k>ma) ma=k;
	}
	int cnt=0;
	for(int i=0; i<=ma+1; i++) {
		a[i]+=b[i];
		if(abs(a[i])>1e-6) cnt++;
//		if(a[i]>=10) {//完全的多此一举啊 
//			a[i]-=10;
//			a[i+1]++;
//		}
	}
	if(!cnt ) printf("%d", cnt);//可能不为0 
	else printf("%d ", cnt);
	for(int i=ma+1,j=0; i>=0; i--) {
		if(abs(a[i])>1e-6) {//不等于0
			if(!j) {
				printf("%d %.1lf", i,a[i]);
				j=1;
			} else printf(" %d %.1lf", i,a[i]);
		}
	}
	return 0;
}

1003 我要通过!,没看懂题,看了题解才懂原来是找规律!这题非常好,刚开始以为题目出的不清楚,其实是自己思维问题,这句话可以理解为一种“递推”,最后的规律就是a*b==c!!

6.1019 数字黑洞:模拟4位数,的降序减升序的结果最后会停在一个地方,坑:

  • 3算0003,所以降序是3000。so不能用to_string,不过可以直接 stoi(),省的做高精度减法了
  • 如果第一个就是6174系列,则直接 printf("7641 - 1467 = 6174");注意是第一个这玩意,否则不要输出
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main() {
	int n,t,x,y,j=0;
	string a,b;
	cin>>n;
	while(1) {
		a=b="";
		t=n;
		for(int i=0; i<4; i++) {
			a+=t%10+'0';//0也会加到前面
			t/=10;
		}
		t=n;
		sort(a.begin(),a.end());//reverse(a.begin(),a.end())原地反转
		for(int i=3; i>=0; i--)
			b+=a[i];
		x=stoi(a);
		y=stoi(b);
		n=y-x;
		if(t==n) {
			if(!j) printf("%04d - %04d = %04d",y,x,n);
			break;			
		}
		else {
			if(!j) {
				printf("%04d - %04d = %04d",y,x,n);
				j=1;
			} else printf("\n%04d - %04d = %04d",y,x,n);
		}
	}
	return 0;
}

case7:Count PAT's,找到一个string中有多少个PAT(可以跳)。乍一看很麻烦 如果左到右遍历的话,但是借鉴了巧妙思路,

  • 其实就是每个A左边有多少P乘以右边有多少T!实现方式也非常巧妙:用两个数组,从左向右标记P的数量,另一个从右向左标记T,最后遍历A,拿这一位的pn*tn这个A的cnt,再把所有A的cnt加起来就是ans
  • 动态数组可以这么申请(AC了),内存也是连续的?
  • 取模问题,这样AC的我之前写的cnt+=xxx%M,错了,不能在+=后面写呀!害怕的话这样写,也AC
#include<iostream>
using namespace std;
const int M=1000000007;
string a;
int main() {
	cin>>a;
	int L=a.length();
	int *pn=new int[L];
	int *tn=new int[L];
	if(a[0]=='P') pn[0]=1;
	if(a[L-1]=='T') tn[L-1]=1;
	for(int i=1,j=L-2; i<L&&j>=0; i++,j--) {
		if(a[i]=='P') pn[i]=pn[i-1]+1;
		else pn[i]=pn[i-1];
		if(a[j]=='T') tn[j]=tn[j+1]+1;
		else tn[j]=tn[j+1];
	}
	int cnt=0;
	for(int i=0; i<L; i++)
		if(a[i]=='A')
			cnt=(cnt%M+(pn[i]%M*tn[i]%M)%M)%M;
	cout<<cnt;
	return 0;
}

case8:Are They Equal

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值