PAT甲级 2020秋准备

2020.2.5

刷以前的题目,20分的开始

第一题(字符串处理)
Kuchiguse (20)
输在翻译和 C++ 中一个特别好用的 reverse(x.begin(),x.end());

第二题(数学)
Consecutive Factors (20)

第三题(见面礼)
A+B in Hogwarts (20)
这道题没什么难度,就考一个翻译。(不粘代码了,没意义。)

第四题

A+B and C (64bit) (20)
两个64位数相加,两种办法:

第一种,判断是否发生溢出 :


x+ 、y+ 结果为负数,一定为true
x -、y-、x+y>=0 (注意等于一定要有) 结果为 false
x、y 一正一负,直接相加比大小


第二种 数组相加(些许麻烦,不过比较好想到)

第五题
Shuffling Machine (20)
这道题,还是看不懂英文,真是硬伤。翻译过来就懂了。
很简单,其实用结构体更好一些。考的是数据结构感觉跟算法没什么关系。用两个数组来存改变前的和已经改变的。写了一个方法来简单点的初始化,不然真的很恶心。没什么说的。

#include
using namespace std;
string a[100];
string La[100];//用来保存仍未移动的 
void Set(char c,int st)
{
     
 for(int i =1 ;i<14;i++)
 {
     
  La[st]=a[st]=c;
   
  if(i<10)
   La[st]=a[st]+=i+'0';
  else 
  {
     
   La[st]=a[st]+='1';
   La[st]=a[st]+=i%10+'0';
  }
  a[st++];
 }
}
int main()
{
     
 Set('S',1);
 Set('H',14);
 Set('C',27);
 Set('D',40);
 La[53] = a[53] = "J1";La[54] = a[54] = "J2";
 
 int re;
 int arr[100];//洗牌规则 
 cin>>re;
 for(int i = 1;i<55;i++)
 {
     
  cin>>arr[i];
 } 
 for(int i = 0 ;i<re;i++)
 {
     
  for(int j = 1;j<55;j++)
  {
     
   int x = arr[j];
   a[x] = La[j];
  }
  for(int j=1;j<55;j++)
   La[j] = a[j];
 }
 for(int i=1;i<55;i++)
  if(i==1)
   cout<<La[i];
  else 
   cout<<" "<<La[i];
} 

第六题
Be Unique (20)
过于简单。在碰见直接找答案,没意思这个题。


#include 
using namespace std;
int main()
{
     
 int n;
 int a[100010];//用来存储出现的顺序 
 int b[100010]={
     0};//用来存储出现次数 
 cin>>n;
 for(int i = 0;i<n;i++)
 {
     
  scanf("%d",&a[i]);
  b[a[i]]++;
 }
 int i;
 for(i = 0;i<n;i++)
 {
     
  if(b[a[i]]==1)
  {
     
   printf("%d",a[i]);
   break;
   } 
 }
 if(i==n)
  printf("None");
}

2020.2.6

Public Bike Management (30)
30分的题,难度还是在的,用了一个小时多吧。
单源最短路径,DFS,剪枝,回溯。(其实没那么难,不剪枝不知道能不能过)
难点:你需要记录,你需要多少车辆和你最后你需要带回多少车辆。
到了一个点,分两种情况:
1、当前点的车辆大于等于一半,那么从这个点中拿走多余的车,自己装着。
2、当前点的车辆小于一半,检查自己手上的车是否够补,优先用自己手上的车来补上,如果不够,那么讲不够的车的数量记录下来,作为需要从总部拿的车辆。

到了故障点一样的操作,不过操作完需要记录,当前拥有的和需要的,作为最后的答案。
用一个Min数组来剪枝
有什么迷的地方可以评论下咱们讨论讨论(。・∀・)ノ,嘿嘿嘿

代码如下:

#include
using namespace std;
string res;			//最终结果 

int Min[502]={
     0};	//到达距离的最小长度 
int Map[502][502];	//地图
int St[502];		//初始车数量 

int n;				//n个站点
int Cmax;			//站点最大存储量
int pb;				//问题站点
int Nway;			//道路 
int Ha = 0,Ne = 9999;//有的、当前需要的 
void dfs(string way,int con[502],int time,int now,int bike,int sta,int have,int need)
//		路线,状态,走到当前点走了几步,现在位置,一共多少辆车,多少个站 ,当前有多少车,当前需要多少车 
{
     
	if(Min[now] < time&&Min[now]!=0) //当前费用大于以前走过的,说明当前道路不是最好的 
		return ;
	if(now == pb&&((Min[pb]>time||Min[pb]==0)||(Min[pb]==time&&(Ne==9999||Ne>need))))
	//判断条件 自己感悟吧 
	{
     
		Ne = need;
		Ha = have;
		Min[pb] = time;
		res = way;	
		return;
	}
		
	if(Min[now] == 0)
		Min[now] = time;
	char tmp;
	for(int i=1;i<=n;i++)
	{
     
		if(i==now||con[i] == 1||Map[now][i] == 0)
			continue;
		tmp = i+'0';
		
		//回溯 
		con[i] = 1; 
		
		if(St[i]+have>=Cmax/2)	//如果说现在拿着的可以补上 
			dfs(way+"->"+tmp,con,time+Map[now][i],i,bike+St[i],sta+1,have+St[i]-Cmax/2,need);
		else 					//补不上 
			dfs(way+"->"+tmp,con,time+Map[now][i],i,bike+St[i],sta+1,0,need+Cmax/2-have-St[i]);	
			
		con[i] = 0;
		
	}
}
int main()
{
     
	
	cin>>Cmax>>n>>pb>>Nway; 
	
	for(int i=1;i<=n;i++)
		cin>>St[i]; 
	for(int i=1;i<Nway+1;i++)
	{
     
		int x,y,w;
		scanf("%d %d %d",&x,&y,&w);
		Map[x][y] = Map[y][x] = w;
	}
	
	int con[502] = {
     1};
	
	dfs("0",con,0,0,0,0,0,0);
		
	cout<<Ne<<" ";
	cout<<res<<" ";
	cout<<Ha;
 } 

2020.2.7

The Largest Generation (25)
第一天写了点20的题,回忆回忆感觉。第二天低产了。第三天这是一个25分的题。这给一个类似于树的,挺简单的。遇见了一个问题。

数组初始化问题(有可能很简单但是的确出问题了)。
我发现,在我没有写这clear函数之前,我的gen[]数组是默认为0的。但是在我写之后我就必须得加上 gen[105] = {0,1}这个初始化操作。
从此中得到的经验:用之前还是别省懒事,一定要初始化!!!
继续改,继续改。
分级别的时候一定是 i,j<=n 小于n 就会结果不对哦~~~
(哈哈哈终于找到为什么错了,开心,恰饭恰饭)

#include 
using namespace std;
typedef struct{
     
	int child[105];//孩子 
	int cnum;//孩子的数量 
	int level;
	int parent;
}Node;
Node a[105];//用来存储家庭
void clear()
{
     
	for(int i =0;i<105;i++)
	{
     
		a[i].cnum = 0;
		if(i!=1)
		a[i].level = 0;
		else 
		a[i].level = 1;
		a[i].parent = 0;
	}
}
int main()
{
     

	int gen[105]={
     0,1};//第i代有多少人 
	int n;//多少人 
	int cn;//多少人有后代 
	
	clear();
	
	cin>>n>>cn;
	for(int i = 0 ;i<cn;i++)
	{
     
		int num;//当前的人 
		int cou;//当前人的后代 
		cin>>num>>cou;
		a[num].cnum = cou;
		
			
		if(a[num].parent!=0&&a[a[num].parent].level!=0&&a[num].level==0)
		//如果说找到过父节点  父节点有level        这个节点没有level 
		{
     
			a[num].level = a[a[num].parent].level+1;
			gen[a[num].level]++;
		}
		
		for(int j = 0;j<cou;j++)
		{
     
			int x;
			cin>>x;
			
			a[x].parent = num;
			if(a[a[x].parent].level!=0&&a[x].level==0)
			{
     
				a[x].level = a[a[x].parent].level+1;
				gen[a[x].level]++;
			}
		}
	}
	for(int i=0;i<=n;i++)
	{
     
		for(int j=0;j<=n;j++)
		{
     
			if(a[j].level==0&&a[a[j].parent].level!=0&&a[j].parent!=0)
			{
     
				a[j].level = a[a[j].parent].level+1;
				gen[a[j].level]++;  
			}
		}
	}
	int max = 1;
	int sum = 0;
	for(int i = 1;i<=cn;i++)
	{
     
		
		sum+=gen[i];
		if(gen[max]<=gen[i])
			max = i;
	}
	cout<<gen[max]<<" "<<max;
} 

2020.2.9

心态有些许崩,两天两道题,愣是不对。
所以写了一个20分的玩了玩,emmm,20的真是舒服
Hello World for U (20)
(答案不粘贴了,过于简单)就当练手了,加油~~。

2020.2.10

状态不是特别好,找了一个25分的题写了写,第一个没写出来,就去找了另一个,还是没写出来,不过后来看了看大神的代码,若有所悟。

题目:
Highest Price in Supply Chain (25)
这个是一个树的深度问题,一开始能看懂题目,但是树学的不怎么地,所以不会做。最后看了看大佬写的,非常简洁明了,于是打开DevC自己又写了一遍。
代码:

#include 
using namespace std;
int n;
int maxDep = 0;
int maxNum = 0;
int tmp;
int root;
vector<int> v[100050];
void DFS(int index,int dep)
{
     
	if(v[index].size() == 0)
	{
     
		if(maxDep == dep)
		{
     
			maxNum++;
		}
		else if(maxDep < dep)
		{
     
			maxDep = dep;
			maxNum = 1;
		}
	}
	for(int i =0;i<v[index].size();i++)
		DFS(v[index][i],dep+1);
} 
int main()
{
     
	double e,r;
	cin>>n>>e>>r;
	for(int i =0;i<n;i++)
	{
     
		cin>>tmp;
		if(tmp == -1)
			root = i;
		else 
			v[tmp].push_back(i); 
	}
	DFS(root,0);
	printf("%.2lf %d",e*pow(1+r/100,maxDep),maxNum);
 } 

PAT甲级 2020秋准备_第1张图片
心得:
个人感觉,这个代码中的树的高度以及存储方法,很是舒服。用Vector来存储树,说实话以前我还真没有想过这种数据结构存储。
个人认为代码可以复用,理解下来背下来~~。


2020.2.11

PAT甲级 2020秋准备_第2张图片
今天继续写,虽然每天写的不多,但希望自己可以坚持下去!!!!
Deduplication on a Linked List (25)
这是一个25分题中比较简单的一个吧,但是就是敲代码麻烦。做了将近40分钟。速度挺慢相对于这道题

代码:

#include 
using namespace std;
typedef struct {
     
	int Num; 
	int next;
}Node;
 
int star;
int n;
int ex[100050]={
     0};//用来判断是否存在 
Node arr[100050];//用来存储 
int Last= -1;//上一个在这个队列中的下标 

int start= -1;//新创建的队列的头部。 
int End = -1;//尾部 

int main()
{
     
	cin>>star>>n;
	int point = 0;
	for(int i =0;i<n;i++)
	{
     
		
		int num,tmp,next;
		scanf("%d %d %d",&tmp,&num,&next);
		arr[tmp].next = next;
		arr[tmp].Num = num;
	}
	int num = 0;
	while(1)
	{
     
		if(ex[abs(arr[star].Num)]==0)
		{
     
			ex[abs(arr[star].Num)] = 1;
			if(num==0)
			{
     
				printf("%05d %d",star,arr[star].Num);
				num++;
			}
			else 
			{
     
				printf(" %05d\n%05d %d",star,star,arr[star].Num);
			}
			Last = star;
			
			if(arr[star].next == -1)
			{
     
				printf(" -1\n");
				break;
			}
			else
				star = arr[star].next;
		}
		else 
		{
     
			if(start == -1)
			{
     
				start = star;
				End = star;
				arr[Last].next = arr[star].next;
				
				arr[start].next = -1;
			}
			else 
			{
     
				arr[End].next = star;
				End = star;
				arr[Last].next = arr[End].next; 
				arr[End].next = -1;
			}
			star = arr[Last].next;
		}
		if(star == -1)
		{
     
			printf(" -1\n");
			break;
		}
	}
	while(1)
	{
     
		if(arr[start].next != -1)
			printf("%05d %d %05d\n",start,arr[start].Num,arr[start].next);
		else 
			printf("%05d %d -1",start,arr[start].Num);
		start = arr[start].next;
		if(start == -1)
			break;
	}
} 

总结:
主要考察数据结构的一道题,因为N小,可以用数组来写,如果大的话,有可能就需要容器之类的结构来写了,较为简单,队列应该会更简单吧~~。

Wow,做到了一个特别舒适的题目,树的层序遍历,搜索二叉树。

Build A Binary Search Tree (30)
刚开始的确不会,连树的层序遍历都忘了,然后打开了百度,输入了题目,出来了大佬的答案,看完之后,惊了,真的精彩!!!

代码:

#include 
using namespace std;
typedef struct {
     
	int l,r,v;
}Node;
Node Tree[1005];
vector<int> p;
int cnt = 0; 

void inOder(int i)
// !!!!!!好方法!!!!!!!!!好方法!!!!!!!!!好方法!!!!!!!!
{
     
	if(Tree[i].l!=-1)
		inOder(Tree[i].l);
	
	Tree[i].v = p[cnt++];
	
	if(Tree[i].r!=-1)
		inOder(Tree[i].r);
}

int main()
{
     
	int n;
	cin>>n;
	for(int i = 0;i<n;i++)
	{
     
		cin>>Tree[i].l>>Tree[i].r;
	}
	for(int i =0;i<n;i++)
	{
     
		int tmp;
		cin>>tmp;
		p.push_back(tmp);
	}
	sort(p.begin(),p.end());
	inOder(0);
	
	queue<Node> q;
	q.push(Tree[0]);
	int flag = 1;
	while(!q.empty())
	{
     
		Node tmp = q.front();
		q.pop();
		if(flag-- == 1)
			printf("%d",tmp.v);
		else
			printf(" %d",tmp.v);
		
		if(tmp.l != -1)
			q.push(Tree[tmp.l]);
		if(tmp.r != -1)
			q.push(Tree[tmp.r]);
	 } 
	
	
} 

主要部分:

void inOder(int i)
{
     
	if(Tree[i].l!=-1)
		inOder(Tree[i].l);
	
	Tree[i].v = p[cnt++];
	
	if(Tree[i].r!=-1)
		inOder(Tree[i].r);
}
/*
这个函数解决这个问题真的绝了,真的太精彩了.
找到树的最左边,那么这就是当前树中最小的数,然后来记录,再向右找。
怎么说呢,这个大佬感觉真的把树的遍历学透了,强!!!!!!
真的帅。
*/

树的层序遍历:
忘了,所以巩固巩固,回忆回忆

	queue<Node> q;
	q.push(Tree[0]);
	int flag = 1;
	while(!q.empty())
	{
     
		Node tmp = q.front();
		q.pop();
		if(flag-- == 1)
			printf("%d",tmp.v);
		else
			printf(" %d",tmp.v);
		
		if(tmp.l != -1)
			q.push(Tree[tmp.l]);
		if(tmp.r != -1)
			q.push(Tree[tmp.r]);
	 } 

总结:
树的层序遍历(队列实现),二叉搜索数的性质(最左边的最小,左小,右大)。(ps:深切的感觉到了算法的魅力)


2020.2.12

废话不多说,继续来做题。
Prime Factors (25)

这是一道找素数题,需要对操作的数字进行优化。
一开始用很是暴力的方法解题:
代码如下:

#include
using namespace std;
bool is_prime(long long x)
{
     
    long long tmp = sqrt(x);
    for(int i = 3;i<=sqrt(x);i++)
    {
     
        if(x%i==0)
            return false;
    }
    return true;
}
int main()
{
     
    long long n;
    cin>>n;
    cout<<n<<"=";
    if(n == 1)
    {
     
        cout<<"1";
        return 0;
    }
     
    long long tmp = n;
     
    for(int i =2;i<=tmp;i++)
    {
     
        int k = 0;//用来记录除以了多少次
        if(is_prime(i))
        {
     
            while(n%i==0)
            {
     
                k++;
                n/=i;
            }
        }
         
        if(k>1)
        {
     
            cout<<i<<"^"<<k;
        }
        else if(k==1)
        {
     
            cout<<i;
        }
        if(n!=1&&k>=1)
            printf("*");
        else if(n==1)
            break;
         
    }
    return 0;
}

但是,提交上去以后,发现Wa了,原因是超时。于是我想了想怎么优化。
就出现了下面部分的改动:

long long tmp = sqrt(n);
//循环开始
 ......
//中间代码省略
....
//循环结束以后
if(n!=1)
	printf("%d",n);

这样我的代码就AC了。
在这里插入图片描述
然后就想看看大家是怎么解题的,就看到了一个思路:
就是将小于50000的质数,全部先用数组记录下来。
如下:

vector<int> prime(50000, 1);
for(int i = 2; i * i < 50000; i++)
        for(int j = 2; j * i < 50000; j++)
            prime[j * i] = 0;

用了Vector容器来解决这个问题。但是由于我不熟悉Vector 于是我用数组又写了一个。

int prime[50005] ={
     1,0,0};
for(int i = 2; i * i < 50000; i++)
        for(int j = 2; j * i < 50000; j++)
            prime[j * i] = 0;
   //判断条件变成了
   if(prime[i]==0)
   {
     
   		......
   }

结果是真的快,嘿嘿嘿,高兴。
在这里插入图片描述
总结:
所以,在遇到需要质数的情况下,有两种办法:
若数字不过于大,推荐使用先初始化的方法。
若数字范围不好确定,最好自己手写一个is_prime()函数。
Vector容器可以定义的时候初始化:
vector v(50000,1); //大小50000,初始化为1(并不是固定50000)。
(写的时候才知道prime是质数的意思 (///∀///) 。)


2020.2.13

PAT甲级 2020秋准备_第3张图片
话不多说,上今天的题目。
Total Sales of Supply Chain (25)
舒服,这个题跟10号的题目差不多,wow,还能记起来怎么写,自己写了一遍,相当流畅,就是出现了编译错误。
**考点:**树的高度问题。
代码:

#include 
using namespace std;
vector<long long> vv[100010];
long long  star[100010] ={
     0};
long long cou[100010] = {
     0};
double p,r;
double sum = 0;
int Be;

void Lv(int now,int lev)
{
     
	if(cou[now]!=0)
	{
     
		double s = p;
		while(lev--)
		{
     
			s = s*(1.0+r/100);
		}
		sum+=s*cou[now];
		return ;
	}
	for(std::size_t i=0;i<vv[now].size();i++)
	{
     
		
		Lv(vv[now][i],lev+1);
	}
}
int main()
{
     
	long long n;
	cin>>n;
	
	cin>>p>>r;
	
	for(int i = 0;i<n;i++)
	{
     
		int tmp;
		cin>>tmp;
		for(int j=0;j<tmp;j++)
		{
     
			int tp;
			cin>>tp;
			vv[i].push_back(tp);
			star[tp] = 1;
		}
		if(tmp==0)
		{
     
			int tp;
			cin>>tp;
			cou[i] = tp; 
		}
	}
	for(int i =0;i<n;i++)
		if(star[i] == 0)
		{
     
			Be = i;
			break;
		}
	Lv(Be,0); 
	printf("%.1lf",sum);
}

遇到的问题:
出现了编译错误,最后调整了一下变量以及函数的名称,例如:level、begin之类的名字,不可以叫,不然的话,会出现编译的问题(当然前提是你用的万能头文件)。


2020.2.14

PAT甲级 2020秋准备_第4张图片
Forwards on Weibo (30)

图的广度搜索,跟前两天深度搜索的感觉差不多,于是刚开始用的DFS(没看出来),然后WA了,看了卡大家写的。
代码:

#include
#include
#include
#include
#include
using namespace std;
vector<int>vt[1005];
bool flag[1005];
int n,level;
int MaxForward(int val){
     
    memset(flag,false,sizeof(flag));
    queue<int>q;
    q.push(val);
    flag[val]=true;
    int sum=1;
    int cntLevel=0;
    int start=0;
    int end=1;
    while(!q.empty()){
     
        val=q.front();
        q.pop();
        start++;
        int size=vt[val].size();
        for(int i=0;i<size;i++){
     
            if(flag[vt[val][i]]==false){
     
                q.push(vt[val][i]);
                flag[vt[val][i]]=true;
                sum++;
            }
        }
        if(start==end){
     //计算层数
            end=sum;
            cntLevel++;
        }
        if(level==cntLevel){
     
            return sum-1;
        }
    }
    return sum-1;
}
int main(){
     
    scanf("%d%d",&n,&level);
    int tmp,val;
    
    for(int i=1;i<=n;i++)
	{
     
        scanf("%d",&tmp);
        for(int j=0;j<tmp;j++)
		{
     
            scanf("%d",&val);
            vt[val].push_back(i);
        }
    }
    
    int k;
    scanf("%d",&k);
    
    for(int i=0;i<k;i++)
	{
     
        scanf("%d",&val);
        val=MaxForward(val);
        printf("%d\n",val);
    }
    return 0;
}

遇到的问题:
就是DFS和BFS,不知道为什么DFS不正确,去发个帖子问问大佬去。其他思路之类的,跟昨天的一样。挺白给的30分。
哈哈哈,AC了,发现哪了错了啊,大家一定要,一定一定要用memset时记得写sizeof(type) 不要忘了,坑死我了。


DFS代码:
个人觉得,效率高,还简单╮(╯▽╰)╭。

#include 
using namespace std;
vector<int> vv[100010];
int rem[1010];
int n;
int L;
int cou;
void DFS(int now,int Lv)
{
     
    if(Lv==L)
        return ;
    for(int i=0;i<vv[now].size();i++)
    {
     
        if(rem[vv[now][i]]++==0)
        {
     
            cou++; 
        }
        DFS(vv[now][i],Lv+1);
    }
}
 
int main()
{
     
    cin>>n>>L;
    for(int i =1;i<=n;i++)
    {
     
        int Num;
        int tmp;
        cin>>Num;
         
        while(Num--)
        {
     
            cin>>tmp;
            vv[tmp].push_back(i);
        }
    }
    int Num;
    cin>>Num;
    for(int i =0;i<Num;i++)
    {
     
        int tmp;
        cin>>tmp;
         
        memset(rem,0, sizeof(int)*1005);
        cou = 0;
        rem[tmp] = 1;
        DFS(tmp,0);
        cout<<cou<<endl;
    }
}

2020.2.15

PAT甲级 2020秋准备_第5张图片
Stack (30)

模拟栈的题目,我用的是数组,难点在于怎么寻找中间数,不过也没那么难,真希望我的秋季赛也能这么简单。

代码:

#include 
using namespace std;
int num[100010] = {
     0};//记录各个数字一共多少个 
int cou = 0;
int main()
{
     
	int n;
	cin>>n;
	
	int a[100010];
	int point = -1;
	
	for(int i =0;i<n;i++)
	{
     
		string tmp;
		getchar();
		cin>>tmp;
		if(tmp == "Pop")
		{
     
			if(point==-1)
			{
     
				printf("Invalid\n");
				continue;
			}
			num[a[point]]--;
			printf("%d\n",a[point--]);
			cou--;
		}
		else if(tmp == "PeekMedian")
		{
     
			if(point == -1)
			{
     
				printf("Invalid\n");
				continue;
			}
			int sum = 0;
			int n = 0;
			if(cou==1)
				printf("%d\n",a[0]);
			else 
			{
     
				int l = cou;
				if(cou%2==1)
					l++;
				while(sum<l/2)
				{
     
					if(sum+num[n] >= l/2)
					{
     
						cout<<n<<endl; break;
					}
						
					sum+=num[n++];
				}
			}
			
		}
		else 
		{
     
			int x;
			cin>>x;
			num[x]++;
			a[++point] = x;
			cou++;
		}
	}
}

总结:
提交完代码之后,发现速度挺慢的,于是网上又找了一个代码提交了上去,发现他也不快,这我就放心了,时间复杂度的确挺高,希望在后面写代码的过程中能想到方法改善代码。


2020.2.16

PAT甲级 2020秋准备_第6张图片
Hashing (25)
比较简单的一道题,但是出现了**开放定址法——平方探测(Quadratic Probing)**这个方法,卡在这个名词上了,查了一下过了。

名词解释:
定理
如果使用平方探测,且表的规模是素数,那么当表至少有一半是空的时候,总能插入新的元素。

代码:

#include 
using namespace std;
int Re[10010]={
     0};
int Po[10010]={
     0};
bool is_prim(int x)
{
     
	if(x==1)
		return false;
		
	int l = sqrt(x); 
	for(int i =2;i<=l;i++)
	{
     
		if(x%i==0)
		return false;
	}
	return true;
}
int main()
{
     
	int m,n;
	int tmp;
	
	cin>>m>>n;
	while(!is_prim(m++));
	m-=1;
	
	memset(Po,-1,sizeof(int)*10000);
	
	for(int i =0;i<n;i++)
	{
     
		cin>>tmp;
		for(int j=0;j<m;j++)
		{
     
			int mod = (tmp+j*j)%m;
			
			if(Re[mod] == 0)//没有数字
			{
     
				Re[mod] = 1;
				Po[i] = mod;
				break;
			}
		}
		
	}
	
	for(int i =0;i<n;i++)
	{
     
		if(i!=0)
			cout<<" ";
		if(Po[i] == -1)
			printf("-");
		else 
			cout<<Po[i]; 
	}
} 

总结:
很简单的一道题,但是需要Hashmap的知识和“平方探测(Quadratic Probing)” 的知识。

2020.2.19

写不出来题,头发越来越长,快疯了。/(ㄒoㄒ)/~~

2020.2.20

今天舒服了,一遍 AC。但是说实话,30分的题,真的有点难,我写了好几个都无法AC。
Shopping in Mars (25)

题目:
求连续几个数凑成一个数,找到浪费最小的。
代码:

#include 
using namespace std;
typedef long long ll;
int n;
ll cou = 0;
int a[100010];
int Min=999;
int Mcou=0;

int rem[100010][2];
int Index = 0;

void DFS(int x,int sum,int star)
{
     
	sum+=a[x];
	
	if(sum >= cou)
	{
     
		if(sum-cou<Min)
		{
     
			Min = sum-cou;
			Mcou=1;
			Index = 0;
			rem[Index][0] = star;
			rem[Index++][1] = x;
		}
		else if(sum-cou ==  Min)
		{
     
			rem[Index][0] = star;
			rem[Index++][1] = x;
			Mcou++;
		}
//		printf("Min = %d,sum = %d\n",Min,sum);
		return ;
	}
	if(x>=n)
		return ;
	
	DFS(x+1,sum,star);
}

int main()
{
     
	cin>>n;
	cin>>cou;
	for(int i =0;i<n;i++)
	{
     
		cin>>a[i];
	}
	
	for(int i =0;i<n;i++)
		DFS(i,0,i);
		
	for(int i =0;i<Index;i++)
	{
     
		printf("%d-%d\n",rem[i][0]+1,rem[i][1]+1);
	}
}
 

总结:
搜索就好了,从当前位置向后搜索,记录起始位置和结束位置,一遍AC,舒服。


2020.2.22

PAT甲级 2020秋准备_第7张图片
Speech Patterns (25)
思想不难,但是实现的问题上我用Map出了问题,让我更仔细地了解到了C++中Map的用法,先粘代码,后面总结。

代码如下:

#include 
using namespace std;
int main()
{
     
	char c;
	string x="";
	int Mnum=0;			//出现最多的字符串出现次数 
	 
	map<string,int> m;
	while(1)
	{
     
		scanf("%c",&c);
		if(c=='\n')
			break;
		if(c>='a'&&c<='z'||c>='A'&&c<='Z'||c>='0'&&c<='9')
		{
     
			if(c>='A'&&c<='Z')
			x+=c+32;
			else
			x+=c;
		}
		else if(x!="")
		{
     
			if(m.count(x)==0)
				m[x] = 0;
			m[x]++;
//			cout<
			if(m[x]>Mnum)
			{
     
				Mnum = m[x];
			}
			x="";
		}
	}
	map<string,int>::iterator it = m.begin();
	while(it != m.end())
	{
     
		if(it->second == Mnum)
		{
     
			cout<<it->first<<" ";break;
		}
		it++;
	}
	cout<<Mnum;

}

心得与总结:

关于Map的:

  1. map中有个方法, map.count(x); 用处是查找Map中是否存在X,若存在返回1,不存在返回0。
  2. map中的顺序是按照key的从小到大排序(string 也不例外)。
  3. std::map>,从大到小排序(type为基础类型,string,int…)
  4. Sort(a,a+n,cmp);是不可以用来给Map容器排序的!!!

这道题简单,但是涨姿势了。


2020.2.22阶段性总结

  1. reverse(str.begin(),str.end()); 函数
  2. 两个64位数相加会±溢出,可以根据得到的结果判断是整数还是负数相加。
  3. clear();这个用法会使没有有**明确的初始化(a[] = {0}就会)**的数组初始值混乱。
  4. vector作为存储数的容器来说,可以存储非特殊的树,很好用。(2.10)
  5. 树的层序遍历方法的回忆。还有一种平衡二叉树的问题,即向左遍历最左下的便是最小的(听起来很容易,但是实际的确没写出来,详情见2.11)
  6. 数量极大的,求素数的问题,可以用开方来解决因为速度而WA的问题。
  7. Vector的初始化问题 vector v(50000,1); //大小50000,初始化为1(并不是固定50000)。
  8. 树的高度 (深度遍历)。
  9. 当在用C++万能头文件的时候 ,不可以将变量名起成level、begin。
    10.在用memset这个方法的时候,第三个参数一定要写上sizeof(type)!!!
  10. 平方探测 :如果使用平方探测,且表的规模是素数,那么当表至少有一半是空的时候,总能插入新的元素PAT甲级 2020秋准备_第8张图片
  11. map中有个方法, map.count(x); 用处是查找Map中是否存在X,若存在返回1,不存在返回0。
  12. map中的顺序是按照key的从小到大排序(string 也不例外)。
  13. std::map默认从大到小排序(type为基础类型,string,int…)
  14. Sort(a,a+n,cmp);是不可以用来给Map容器排序的!!!

2020.02.25

三天没有更新,但是三天一直在写蓝桥杯,啊,真的难啊,快难哭了/(ㄒoㄒ)/~~。

你可能感兴趣的:(PAT,算法,c++)