想要在pat甲级拿80到90分?陈越姥姥给出的建议如下:
首先有十分钟拿下乙级15分题的本事。 然后要能在半小时内完成乙级20分题1道。
接下来训练自己45分钟完成乙级25分题。 这时你有了2.5小时满乙级的本事!
下面改做甲级英文题。 要有用十分钟读完4题的本事。
20分钟写完20分题并至少过样例。 1小时内写完2道25分题并至少过样例。1小时写完最难题并至少过样例。 此时你应该有70分左右了,最后半小时拚命过90吧!
#include
#include
#include
using namespace std;
int main(){
string s1,s2;
cin>>s1;
cin>>s2;
sort(s1.begin(),s1.end());
sort(s2.begin(),s2.end());
//cout<
//排序之后更有效率,对之后的思路很关键
int i=0,j=0,ans=0;//i,j分别记录目前s1,s2的比较位置
while(j<s2.size()){
//find 函数 返回jk 在s 中的下标位置
int position = s1.find(s2[j],i);//s1指定位置之后是否有目前s2这个值
if(position!=s1.npos){
ans++;i=position+1;//有的话,更新s1能够查找的范围,ans++
//cout<
}
j++;
}
if(ans==s2.size()){
cout<<"Yes "<<s1.size()-s2.size();
}else{
cout<<"No "<<s2.size()-ans;
}
return 0;
}
sum up:C++ string中的find()函数
#include
#include
#include
using namespace std;
int main(){
int N;
cin>>N;
vector<int> initial(N,0);
vector<int> res(N,0);
for(int i=0;i<N;i++){
cin>>initial[i];
}
for(int i=0;i<N;i++){
cin>>res[i];
}
int i=1;
while(i<N&&res[i]>=res[i-1]){
i++;
}
int j=i;
while(j<N&&res[j]==initial[j]){
j++;
}
if(j==N){
cout<<"Insertion Sort"<<endl;
sort(initial.begin(),initial.begin()+i+1);
}else{
cout<<"Merge Sort"<<endl;
int flag=0;
for(int m=2;m/2<=N;m=m*2){
if(initial==res){
flag=1;
}
for(int k=0;k<=N;k=k+m){
int end=(k+m>N)?N:(k+m);
sort(initial.begin()+k,initial.begin()+end);
}
if(flag==1){
break;
}
}
}
for(int i=0;i<N;i++){
cout<<initial[i]<<" ";
}
return 0;
}
分析:
一开始以为是要自己写插入和归并算法,写了出来之后样例对了一半TAT,才发现并不是考察这个!
重温了一遍归并算法,注意条件(i<=mid)有等号
实际上是首先判断是不是插入,如果前面有序,后面无序的部分两个数组一致,那么是插入排序,使用sort指定范围排序即可
如果是归并排序,那么首先找到是哪一步的归并排序,然后输出即可,注意后面不满足的情况
#include
#include
#include
#include
using namespace std;
int main(){
long long N;
cin>>N;
int m=sqrt(N)+1;
vector<int> res;
int count=0,temp=1;
int ans=0,l=0;
for(int i=2;i<=m;i++){
if(N%i==0){
count++;
temp=temp*i;
res.push_back(i);
}
} //得出所有可能的因子
int n=res.size();
if(n==0){
cout<<1<<endl<<N;//素数只有它自己本身
} else if(n==1){
cout<<1<<endl<<res[0];//只有一个因数,那么就是它自己本身
}else{
//情况多的时候分析
for(int i=0;i<n;i++){
temp=res[i];//初始化循环条件
count=1;
for(int j=i;i<n;j++){
if((res[j+1]-res[j]==1)&&(N%(temp*res[j+1])==0)){
temp=temp*res[j+1];
count++;
}else{
break;//不符合条件换下一个寻找
}
}
if(count>ans){
//如果有更优解,则记录下开始和结束位置,并记录最优解的大小
ans=count;
l=i;
}
}
cout<<ans<<endl;
cout<<res[l];
for(int i=1;i<ans;i++){
cout<<'*'<<res[i+l];
}
}
return 0;
}
sum up:
发现英文题会容易忽视很多细节,导致最后的解答半对
注意点
1:素数的输出结果是1,该数本身(测试样例6)
2:只有一个因数,即,因数没有连续的比如1024,输出结果是 1,2(2是它的最小因素)
3:连续的相乘得是N的因数,即例子N=120,其最长连续因子为2∗3∗4∗5,而不是2∗3∗4∗5∗6
4:6的结果是2,2*3,所以sqrt(N)还得加1
重点:既要连续,连续之后还得是因子
#include
#include
using namespace std;
const int maxn=100001;
struct Node{
int address,key,next;
int num=2*maxn;
}node[maxn];
bool exist[maxn];
int cmp1(Node a,Node b){
return a.num<b.num;
}
int main(){
int begin, n, cnt1=0,cnt2=0,a;
scanf("%d%d",&begin,&n);
for(int i=0;i<n;i++){
scanf("%d",&a);
scanf("%d%d",&node[a].key,&node[a].next);
node[a].address=a;
}
for(int i=begin;i!=-1;i=node[i].next){
if(exist[abs(node[i].key)]==false){
exist[abs(node[i].key)]=true;
node[i].num = cnt1;
cnt1++;
}else{
node[i].num=maxn+cnt2;
cnt2++;
}
}
sort(node, node+maxn,cmp1);
int cnt=cnt1+cnt2;
for(int i=0;i<cnt;i++){
if(i!=cnt1-1&&i!=cnt-1){
printf("%05d %d %05d\n",node[i].address,node[i].key,node[i+1].address);
}else{
printf("%05d %d -1\n",node[i].address,node[i].key);
}
}
return 0;
}
最后采用了柳神的代码,PAT的链表实际上并不能考察到链表的转变,反而是在维护vector数组。自己写的代码只对了一半的样例,就不展示了……
#include
#include
using namespace std;
int main(){
int n;
cin>>n;
double sum=0.0,temp;
for(int i=1;i<=n;i++){
cin>>temp;
sum=sum+temp*i*(n-i+1);
}
printf("%.2f",sum);
return 0;
}
学习他人思路,利用双指针pq判断符合要求的区间
#include
#include
#include
#include
using namespace std;
static bool cmp(int a , int b){
return a>b;
}
int main(){
int N;cin>>N;
vector<int> a(N);
for(int i=0;i<N;i++){
cin>>a[i];
}
sort(a.begin(),a.end(),cmp);
int n=sqrt(N);
while(N%n!=0){
n--;
}
int m=N/n,t=0;
vector<vector<int> > b(m, vector<int>(n));
int level = m / 2 + m % 2;
for (int i = 0; i < level; i++) {
for (int j = i; j <= n - 1 - i && t <= N - 1; j++)
b[i][j] = a[t++];
for (int j = i + 1; j <= m - 2 - i && t <= N - 1; j++)
b[j][n - 1 - i] = a[t++];
for (int j = n - i - 1; j >= i && t <= N - 1; j--)
b[m - 1 - i][j] = a[t++];
for (int j = m - 2 - i; j >= i + 1 && t <= N - 1; j--)
b[j][i] = a[t++];
}
for (int i = 0; i < m; i++) {
for (int j = 0 ; j < n; j++) {
printf("%d", b[i][j]);
if (j != n - 1) printf(" ");
}
printf("\n");
}
}
#include
#include
#include
#include
#include
#include
using namespace std;
int main(){
int N;
double P,r;
cin>>N>>P>>r;
vector<int> count;
vector<vector<int> > b;
for(int i=0;i<N;i++){
int num=0;
cin>>num;
if(num==0) {
count.push_back(i);
}
vector<int> temp;
temp.push_back(num);
for(int j=1;j<=num;j++){
int t;cin>>t;
temp.push_back(t);
}
b.push_back(temp);
}
vector<double> node(N,P);
queue<int> q;
int index=0,i=0;
while(index<N){
for(int j=1;j<b[i].size();j++){
q.push(b[i][j]);
node[b[i][j]]=node[i]*(1+r*0.01);
}
i=q.front();q.pop();
index++;
}
double minde=INT_MAX*2.0;
int cnt=0;
for(int i=0;i<count.size();i++){
minde=min(minde,node[count[i]]);
}
for(int i=0;i<count.size();i++){
if(node[count[i]]==minde){
//printf("\n%0.4f %f\n",minde,node[count[i]]);
cnt++;
}
}
printf("%0.4f %d",minde,cnt);
return 0;
/*
for(int i=0;i
}
分析,学会使用队列,看别人的代码,觉得输入输出这块非常的简洁,自己写代码,感觉写一长串的那种。如果是同种类型的最好声明能在同一行,用scanf效果会更好。
提交了一次,发现是部分正确,网上找了问题所在,发现是自己定的初始最小值太小了,不够大,有一个头文件#include
#include
#include
#include
using namespace std;
vector<int> father,isRoot;
int cmp1(int a, int b){
return a>b;//降序排序
}
int findFather(int x){
//查找根节点
int a = x;
while(x!=father[x]){
//自己的父亲不是根节点
x=father[x];
}
while(a!=father[x]){
//查找父亲,直至很找到根节点
int z=a;
a=father[a];
father[z]=x;
}
return x;
}
void Union(int a,int b){
int faA=findFather(a);
int faB=findFather(b);
if(faA!=faB) father[faA]=faB;//两个人不统一,创建关系
}
int main(){
int n,k,t,cnt=0;
int course[1001]={
0};
scanf("%d",&n);
father.resize(n+1);
isRoot.resize(n+1);
for(int i=1;i<=n;i++){
father[i]=i;
}
for(int i=1;i<=n;i++){
scanf("%d:",&k);
for(int j=0;j<k;j++){
scanf("%d",&t);
if(course[t]==0){
course[t]=i;
}//每个社交圈的结点号是人的编号,而不是课程。课程是来判断是否处在一个社交圈的
Union(i,findFather(course[t]));
}
}
for(int i=1;i<=n;i++){
isRoot[findFather(i)]++;//如果有相同的父亲的话++
}
for(int i=1;i<=n;i++){
if(isRoot[i]!=0)cnt++;
}
printf("%d\n",cnt);
sort(isRoot.begin(),isRoot.end(),cmp1);
for(int i=0;i<cnt;i++){
printf("%d",isRoot[i]);
if(i!=cnt-1)printf(" ");
}
return 0;
}
分析:并查集的套路还不是很清楚,需要多练习同样的题目
#include
#include
#include
using namespace std;
int main(){
int n, cnt=0;
cin>>n;
double sum=0,temp;
char a[50],b[50];
for(int i=0;i<n;i++){
cin>>a;
sscanf(a,"%lf",&temp);
sprintf(b,"%.2f",temp);
int flag=0;
for(int j=0;j<strlen(a);j++){
if(a[j]!=b[j])flag=1;
}
if(flag==0&&temp>=-1000&&temp<=1000){
sum+=temp;
cnt++;
}else{
printf("ERROR: %s is not a legal number\n",a);
}
}
if(cnt==0){
printf("The average of 0 numbers is Undefined");
}else if(cnt==1){
printf("The average of 1 number is %0.2f",sum);
} else{
printf("The average of %d numbers is %0.2f",cnt,sum/cnt);
}
return 0;
}
#include
#include
#include
using namespace std;
struct people{
string name;
int height;
}p[10002];
bool cmp1(people a,people b){
return a.height != b.height ? a.height > b.height : a.name < b.name;
}
int main(){
int num[20]={
19,17,15,13,11,9,7,5,3,1,0,2,4,6,8,10,12,14,16,18};
int n,k,h;
cin>>n>>k;
for(int i=0;i<n;i++){
cin>>p[i].name>>p[i].height;
}
sort(p,p+n,cmp1);
int row=n/k;
int last=k+n%k;
for(int i=0;i<last;i++){
cout<<p[num[i+10-(last)/2]].name;
if(i!=last-1)cout<<" ";
}
cout<<endl;
for(int j=1;j<row;j++){
for(int i=0;i<k;i++){
cout<<p[num[i+(11-k)/2+5]+j*k+n%k].name;
if(i!=k-1)cout<<" ";
}
if(j!=row-1)cout<<endl;
}
return 0;
}
这个答案只能过前三个样例,因为搞错了k的含义,k的意思是行数,而非每行个数
#include
#include
#include
#include
using namespace std;
struct people{
string name;
int height;
}p[10002];
bool cmp1(people a,people b){
return a.height != b.height ? a.height > b.height : a.name < b.name;
}
int main(){
int num[20]={
19,17,15,13,11,9,7,5,3,1,0,2,4,6,8,10,12,14,16,18};
int n,k,h;
cin>>n>>k;
for(int i=0;i<n;i++){
cin>>p[i].name>>p[i].height;
}
sort(p,p+n,cmp1);
int row=k;
int t=0,m;
while(row){
if(row==k){
m=n-n/k*(k-1);
}else{
m=n/k;
}
vector<string> ans(m);
ans[m/2]=p[t].name;
//左边一列
int j=m/2-1;
for(int i=t+1;i<t+m;i=i+2){
ans[j--]=p[i].name;
}
//右边一列
j=m/2+1;
for(int i=t+2;i<t+m;i=i+2){
ans[j++]=p[i].name;
}
//输出当前排
cout<<ans[0];
for(int i=1;i<m;i++){
cout<<" "<<ans[i];
}
if(row!=1)cout<<endl;
t=t+m;
row--;
}
return 0;
}