PAT甲级题库打卡—【实时更新】—最新23.8.31

模拟

1001 A+B Format

就是用%/ 注意,最后输出的时候printf("%03d",ans) 就可以保持三位左补0;

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

// 模拟 

int main()
{
    int a,b;
    cin >> a >> b;
    int c = a+b;
    
    vector<int> ans;
    int tmp = c;
    
    do
    {
    	ans.push_back(abs(tmp%1000));
    	tmp /= 1000;
	}while(tmp);
	
	if(c < 0)cout << '-';
	
	if(c == 0)
	{
		cout << tmp;
		return 0;
	}
	
	int i = ans.size() - 1;
	
	printf("%d",ans[i--]);
	
	for(; i >= 0; i--)
		printf(",%03d",ans[i]);  // 3表示输出三位数字 0表示左补充0  学到了!! 
	
	return 0;
}

1002 A+B for Polynomials

第一天死都过不了第2个测试点,后来知道原来错在:浮点数与0比较没有加fabs绝对值 。 本题直接浮点数==0 也能过,但是对一般题目而言浮点数与0比较还是统一用作差绝对值<一个极小数,(这个点某个夏令营也被问到了,当时短路了没回答上)原因是浮点数在电脑中是01二进制存储的。不是那么绝对精确。

AC代码:

#include<iostream>
#include<algorithm>
#include<cmath>
#define eps 1e-9

using namespace std;

const int N = 1010;

float a[N];

int main()
{
	int t = 2;
	while(t--)
	{
		int k;
		cin >> k;
		for(int i = 0; i < k; i++)
		{
			int idx;
			float x;
			cin >> idx >> x;
			a[idx] += x;
		}
	}
    
	int num = 0;
	for(int i = 0; i < N; i++)
		if( fabs(a[i]) > eps)num++;  // 测试点2一直过不了的原因是没有加fabs绝对值 
	cout << num;
	
	for(int i = N-1; i >= 0; i--)
	{
		if(fabs(a[i]) > eps)
		{
			printf(" %d %.1f",i,a[i]);
		}
	}
	return 0;
} 

哈希

84 1084 Broken Keyboard

就一个简单hash,但我思路和代码能力不能支持几分钟敲出来

AC代码:

#include<iostream>
#include<string>

using namespace std;

int h[40];


int main()
{
	string ori;
	string now;
	cin >> ori >> now;
	
	for(int i = 0; i < ori.size();i++)
		if(ori[i] >= 'a' && ori[i] <= 'z')ori[i] -= 32;
	
	for(int i = 0; i < now.size();i++)
		if(now[i] >= 'a' && now[i] <= 'z')now[i] -= 32;
	
	for(int i = 0; i < now.size();i++)
	{
		if(now[i] >= 'A' && now[i] <= 'Z')h[now[i] - 'A']++;  //0-25
		else if(now[i] >= '0' && now[i] <= '9')h[now[i] - '0'+26]++;  //26-35
		else if(now[i] == '_')h[36]++;
	}
	
	
	for(int i = 0; i < ori.size();i++)
	{
		if(ori[i] >= 'A' && ori[i] <= 'Z') //0-25
		{
			if(h[ori[i] - 'A'] == 0)
			{
				printf("%c",ori[i]);
				h[ori[i] - 'A'] = 1;
			}
		}
		else if(ori[i] >= '0' && ori[i] <= '9')//26-35
		{
			if(h[ori[i] - '0'+26] == 0)
			{
				printf("%c",ori[i]);
				h[ori[i] - '0'+26] =1;
			}
		}
		else if(ori[i] == '_')
		{
			if(h[36] == 0)
			{
				printf("%c",ori[i]);
				h[36]=1;
			}
		}
	}
	
	return 0;
}

92 1092 To Buy or Not to Buy

AC代码:

#include<iostream>
#include<string>

using namespace std;

const int N = 70;

int hash1[N];

int main()
{
	string t,my;
	cin >> t >> my;
	for(int i = 0; i < my.size();i++)
	{
		if(my[i] >= '0' && my[i] <= '9')  //0-9
		{
			hash1[my[i] - '0']++;
		}
		else if(my[i] >= 'a' && my[i] <= 'z')  //10-35
		{
			hash1[my[i] - 'a'+10]++;
		}
		else   //36-61
		{
			hash1[my[i] - 'A'+35]++;
		}
	}
	
	for(int i = 0; i < t.size(); i++)
	{
		if(t[i] >= '0' && t[i] <= '9')  //0-9
		{
			hash1[t[i] - '0']--;
		}
		else if(t[i] >= 'a' && t[i] <= 'z')  //10-35
		{
			hash1[t[i] - 'a'+10]--;
		}
		else   //36-61
		{
			hash1[t[i] - 'A'+35]--;
		}
	}
	
	int num = 0;
	for(int i = 0; i < 62; i++)
	{
		if(hash1[i] > 0)num+=hash1[i];// 空缺的 
	}
	 
	if(num)
	{
		cout << "No " << num;
	} 
	else
	{
		cout << "Yes " << t.size() - my.size();
	}
	return 0;
}


/*
ppRYYGrrYBR225
YrR8RrY
*/

贪心

70 1070 Mooncake

测试点2好像是一定开double才行,测试点3不知道什么问题一直过不了。

#include<iostream>
#include<string.h>
#define eps 1e-6
using namespace std;

const int N = 1010;

double hold[N];
double price[N];
double singlep[N];
bool vis[N];

int main()
{
	int type;
	double need;
	scanf("%d %lf", &type, &need);
	
	for(int i = 0; i < type; i++)
		// cin >> hold[i];
        scanf("%lf",&hold[i]);
    
	for(int i = 0; i < type; i++)
		// cin >> price[i];
        scanf("%lf",&price[i]);
	
	for(int i = 0; i < type; i++)
		singlep[i] = price[i]/hold[i];
	
	double ans = 0;
	
	while(need>eps)
	{
		double max_sp = -0xffff;  //找到最贵的 
		int max_idx = 0;
		for(int i = 0; i < type; i++)
		{
			if(!vis[i])
			{
//				cout << "singlep[i]:" << singlep[i] << endl;
				if(singlep[i] >= max_sp)
				{
					max_sp = singlep[i];
					max_idx = i;
				}
			}
		}
		vis[max_idx] = 1;
		if(hold[max_idx] >= need)
		{
			if(hold[max_idx] == need)
			{
				ans += price[max_idx];
			} 
			else ans += singlep[max_idx]*need;
			need = 0;
            break;
		}
		else
		{
			need -= hold[max_idx];
			ans += price[max_idx];
//			cout << "need	" << need << "ans	 " << ans << endl;
		}
	}
	printf("%.2lf",ans);
} 


/*

3
982
32 888 32
9 1000 22

*/



37 1037 Magic Coupon

比较容易实现的贪心。

AC代码:

#include<iostream>
#include<algorithm>
using namespace std;

const int N = 1e5+10;

int a[N];
int b[N];

bool cmp(int x,int y)
{
	return x>y;
}

int main()
{
	// 贪心的策略:
	/*
	(1)两行从大到小排序
	(2)正的和正的乘 
	(3)之后从右边开始负的和负的乘
	*/ 
	
	int n;
	cin >> n;
	for(int i = 0; i < n; i++)
		cin >> a[i];
	
	int m;
	cin >> m;
	for(int i = 0; i < m; i++)
		cin >> b[i];
	
	
	sort(a,a+n,cmp);
	sort(b,b+m,cmp);
	
	long long ans = 0;
	
	for(int i = 0;a[i] > 0; i++ )
		if(i < m && b[i] > 0)
		{
			ans += a[i] * b[i];
//			cout << "ans" << ans << endl;
		}
			
	
	int j = m-1;
	for(int i = n-1; a[i] < 0 && i >= 0; i--)
	{
		if(j >= 0 && b[j] < 0)
		{
			ans+=a[i]*b[j--];
		}
		else
			break;
	}
	
	cout << ans << endl;
	
	return 0;
}


38 1038 Recover the Smallest Number

一开始我的思路:
/*
初步思路是
从高到低位数依次升序

如果两个数前面k位都相同
如果两个都有k+1位 那就按照k+1位置升序
如果一个有大于k位 另一个只有k个 则前者的k+1与另一个的第1位比较 升序 

*/
但后来在cmp的return一个很细节的语法卡了很久。解决之后。

一个测试点

2 0000 0000  这个要处理

之后发现对于

2 00002 1000 别人的代码答案竟然是21000 不是10002 明白了题意理解错了,前导0也加入排序中不过最后输出时去掉前导0即可。

错误代码:

#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;

const int N = 1e4+10; 

string a[N];
int num = 0;

int tmpa[10];
int tmpb[10];
int cnta;
int cntb;

 
/*
初步思路是
从高到低位数依次升序

如果两个数前面k位都相同
如果两个都有k+1位 那就按照k+1位置升序
如果一个有大于k位 另一个只有k个 则前者的k+1与另一个的第1位比较 升序 

*/

void split(int x,int* u,int &cnt)
{
	while(x)
	{
		u[cnt++] = x%10;
		x /= 10;
	}
	int l = 0,r = cnt - 1;
	while(l < r)
	{
		swap(u[l],u[r]);
		l++;
		r--;
	}

	return;
}

bool cmp(int x,int y)
{
	
	memset(tmpa,0,sizeof(tmpa));
	memset(tmpb,0,sizeof(tmpb));
	cnta = 0;
	cntb = 0;
	
	split(x,tmpa,cnta);
	split(y,tmpb,cntb);
	
	int i = 0; 
	while(i < cnta && i < cntb)
	{
		if(tmpa[i] != tmpb[i])
		{
			return tmpa[i]<tmpb[i]; // 321 327 
		}
		else
		{
			i++;
		}
	}
	
	if(i < cnta)  // 3215 321 
	{
	    return tmpa[i]<tmpb[0];
	}
	else if(i < cntb)  // 321 3211
	{
	    return !(tmpb[i]<tmpa[0]);
	}

	return 1;// 两个数相等 
}

int main()
{
	int n;
	cin >> n;
	
	for(int i = 0; i < n; i++)
	{
		int x;
		cin >> x;  // 00002 1000  应该输出21000 而不是100021 
		
		if(x)  //去掉0 
			a[num++] = x; 
	}
	
	sort(a,a + num,cmp);
	
	if(n != 0 && num == 0)
	{
		cout << 0 << endl;
		return 0;
	}
	
	for(int i = 0; i < num; i++)
		printf("%d",a[i]);
	
	return 0;
}

/*
5
1002 0003 9 3218 0 32
*/

看了题解,学习了别人的思想直接用string来做,两个string 选可以组成更小数的排序。AC代码:

#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;

const int N = 1e4+10; 

string a[N];

bool cmp(string x,string y)
{
	return x+y < y+x;
}

int main()
{
	int n;
	cin >> n;
	
	for(int i = 0; i < n; i++)
	{
		string x;
		cin >> x;  // 00002 1000  应该输出21000 而不是100021 
		a[i] = x;
	}
	
	sort(a,a + n,cmp);
	
	string fin = "";
	for(int i = 0; i < n;i++)fin += a[i];
	
	int flag = 0;
	for(int i = 0; i < fin.size();i++)
	{
		if(fin[i] != '0' || (fin[i] == '0' && flag))
		{
			cout << fin[i];
			flag = 1;
		}
		else
		{
			if(!flag)continue;
		}
	}
	if(!flag)cout << 0;
	return 0;
}

/*
5
1002 0003 9 3218 0 32
*/

二分

85 1085 Perfect Sequence

一个二分,注意一个关于long long的语法知识

long long res=  a[i]*p;    // 这样错误 因为右边没有强制转换会爆int!

long long res=  (long long)a[i]*p;    // 这样正确。

#include<iostream>
#include<algorithm>

using namespace std;

const int N = 1e5+10;

int a[N];
int n;

int dic(int i,int j,long long res)//找小于等于res的最大idx
{
	int l = i;
	int r = j;
	while(l<r)
	{
		int mid =(l+r+1)>>1;
		if(a[mid] > res)r = mid - 1;
		else l = mid;
	}
	return (l - i + 1);
}


int main()
{
	int p;
	cin >> n >> p;
	
	for(int i = 0; i < n; i++)
		scanf("%d",&a[i]);
	
	sort(a,a+n);
	
	int ans = 0;
	for(int i = 0; i < n; i++)
	{
        long long res=  (long long)a[i]*p;
        
		// long long res = a[i];
		// res*=p;
		
		int tmp = dic(i,n-1,res); //找小于等于res的最大idx
		ans = max(ans,tmp);
	}
	cout << ans << endl;
	return 0;
}
 

10 1010 Radix

初步思路:

把确定进制的数转成10进制的,设为 p,另外一个数,设为 u,二分查找它的进制,设为  k。

坑:(学习别的题解)

(1)k的下限:不是2,是因为在二分中某个tmpk进制 可能出现太小 不满足u(如,u=9 但是tmpk是2进制)。是u的值的最高位表示的数+1。

(2)k的上限: 不是我一开始预想的最大进制36。那 k 的最大值是?k最大值是p。

原因是:当u只有一位数时,那么u最大可以取z,但z最小的满足的进制就是36 再往上没有意义,都是表示35。当u不止一位数时候,先考虑它两位数,那最小的表示就是10,未来使得(10)k = p,那么k就是p即可,当u最大时候k越小,所以k的最大值是p。其他题解有说是p+1,是考虑到如:10 a 1 10 这样的样例,他们的代码过不了 但我的代码是可以的。所以max_k = p,写成max_k = max(min_k,p)也行。

(3)考虑 0 0 1 10 , 8 8 1 10 样例

(4)二分过程中,mid进制的数(long long进制的数)会爆long  long,变成负数。

(5)很多过程中与long long涉及的变量全都要longlong 

#include<iostream>
#include<algorithm>
#include<string>
 
using namespace std;

// 坑4 很多过程中与long long涉及的变量全都要longlong 

long long turn_radix(string x,long long p1)
{
	string tmpx = x;
	long long ans = 0;
	long long p = 1;
	while(!x.empty())
	{
		char a = x.back();
		x.pop_back(); 
		int a1 = 0;
		
		if(a >= '0' && a <= '9')a1 = a - '0';
		else a1 = a - 'a'+10;
		
		ans += a1*p;
		p*=p1;
	}
//	cout <<  p1 << " 进制的 " << tmpx << " 是:" << ans <<  endl;
	return ans;
}

int main()
{
	string n1,n2;
	int tag,radix;
	
	cin >> n1 >> n2 >> tag >> radix;
	
	long long tmp_n1 = 0;
	string tmp_n2 = "";
	if(tag == 1)
	{
		// n1是radix进制
		tmp_n1 = turn_radix(n1,radix);
		tmp_n2 = n2;
	}
	else
	{
		// n2是radix进制 
		tmp_n1 = turn_radix(n2,radix);
		tmp_n2 = n1;
	}
	
	// 二分判断进制
	char t = '0';
	for(int i = 0; i < tmp_n2.size();i++)
		if(tmp_n2[i] > t)t = tmp_n2[i];
	
	long long l  = 0;  // 坑1:最小进制为最高位代表的数+1 
	if(t >= '0' && t <= '9')l = t - '0' + 1;
	else l = t - 'a' + 10 + 1;
	
	if(l < 2)l = 2;
	
	long long r = max(l,tmp_n1);  // 坑2:最大进制为已知的十进制数 
//	long long r =  tmp_n1;  // 也能过 

	
	while(l < r)
	{
		long long mid = (l + r) >> 1;
		long long tmpr = turn_radix(tmp_n2,mid);  // 坑3 :mid进制的数(long long)会爆long long 
		
		if(tmpr >= tmp_n1 || tmpr < 0)
			r = mid;
		else l = mid + 1;
	}
	
	if(turn_radix(tmp_n2,l) == tmp_n1 )
		cout << l << endl;
	else
		cout << "Impossible" << endl;
	
	return 0;
} 

双指针

29 1029 Median

归并排序的合并两个有序序列。测试点3,6坑: 坑: 测试点3,6:一个数组很小 一个很大 小的那个每到中位数就结束了

#include<iostream>

using namespace std;

const int N = 2e5+10;

int a[N];
int b[N];

int main()
{
	int n;
	cin >> n;
	for(int i = 0; i < n; i++)
		scanf("%d",&a[i]);
	
	int m;
	cin >> m;
	for(int i = 0; i < m; i++)
		scanf("%d",&b[i]);
		
	int k;
	if((n+m)%2 == 1)k = (n+m)/2+1;
	else k = (n+m)/2;
	int i = 0;
	int j = 0;
	int u = 0;
	int ans = 0;
	while(u < k && i < n && j < m) 
	{
		if(i < n && a[i] <= b[j]){ans = a[i];i++;u++;}
		else if(j < m && a[i] > b[j]) {ans = b[j];j++;u++;}
	}
	while(u < k && i < n){ans = a[i];i++;u++;}  // 坑: 测试点3,6:一个数组很小 一个很大 小的那个每到中位数就结束了
	while(u < k && j < m){ans = b[j];j++;u++;}
	cout << ans << endl;
}

新思路

1 左右两次遍历大法

1093 Count PAT's

暴力肯定超时,对于每个A的答案就是左边的P的个数*右边T的个数。所以一开始先把每一个i的左边及自身占的 P 的个数存到一个数组里面。T 同理。 只不过可以在和遍历A求答案的时候顺路计算了。AC代码:

#include<iostream>

using namespace std;

const int N = 1e5+10;
const int MOD = 1000000007;

typedef long long ll;

int leftpnum[N];

int main()
{
	string x;
	cin >> x;
	for(int i = 0; i < x.size();i++)
	{
		if(i == 0)
		{
			if(x[i] == 'P')leftpnum[i] = 1;
			else leftpnum[i] = 0;
		}
		else
		{
			if(x[i] == 'P')leftpnum[i] = leftpnum[i-1]+1;
			else leftpnum[i] = leftpnum[i-1];
		}
	}
	ll ans = 0;
	int num = 0;
	for(int i = x.size()-1;i >= 0; i--)
	{
		if(x[i] == 'T')num++;
		else if(x[i] == 'A') ans += (ll)(leftpnum[i]*num)%MOD;
	}
	cout << ans%MOD << endl;
}

1101 Quick Sort

我一开始思路就是归并排序求逆序对的板子改一下,但是查了一下一个题最多开1.6e7的内存。我这个解法要1e5+1e9爆了,如果改成map 查询的时候还要再乘上logn,即(n*logn*logn) 会爆。代码如下:

#include<iostream>
#include<map>
using namespace std;

const int N = 1e5+5;
//const int M = 1e9+5;
//一般算法题就 撑死1.6e7  

int a[N];
map<int,int> t;
int tmp[N];

void guibing(int l,int r)
{
	if(l >= r)return;
	
	int mid = (l+r) >> 1;
	guibing(l,mid);
	guibing(mid+1,r);
	
	int i = l;
	int j = mid+1;
	
	int k = 0;
	
	while(i <= mid && j <= r)
	{
		if(a[i] <= a[j])tmp[k++] = a[i++];
		else{
			t[a[i]] = 0;
			t[a[j]] = 0;
			tmp[k++] = a[j++];
		}
	}
	
	while(i <= mid)tmp[k++] = a[i++];
	while(j <= r)tmp[k++] = a[j++];
	
	for(int u = 0,i = l; u < k ; u++)a[i++] = tmp[u];
	return;
}

int main()
{
	int n;
	cin >> n;
	
	int max_idx = -1;
	for(int i = 0; i < n; i++)
	{
		scanf("%d",&a[i]);
		t[a[i]] = 1;
		max_idx = max(max_idx,a[i]);
	}

	guibing(0,n-1);

    int num = 0;
	for(int i = 1; i <= max_idx; i++)
		if(t[i])num++;

    cout << num << endl;
    
//    for(int i = 0; i < n; i++)
//	{
//		printf("%d ",a[i]);
//	}
//    
    int ok = 0;
    for(int i = 1; i <= max_idx; i++)
		if(t[i])
        {
            if(!ok)
            {
                cout << i ;
                ok = 1;
            }
            else
            cout << " " << i ;
        }
	
	return 0;
}

后面改成答案的解法,和1093思路雷同的。

AC代码:

还有几个点没过made  8.7

数学

1 分数

1081 Rational Sum

具体分数的表示,化简,加减乘除,输出见算法笔记。

【语法】

过程中我遇到一个及其傻逼的语法问题,在scanf中多写了一个 \n,导致每次输入完第二个了才输出上一个。像下面这个:

scanf("%lld/%lld\n",&tmp.up,&tmp.down);   // scanf 不要写/n  不然会导致输入错误!!!!! 
#include<iostream>
#include<algorithm>

using namespace std;

typedef long long ll;

const int N = 120;

class fra
{
	public:
	ll up;
	ll down;
	
	fra(ll a = 0,ll b = 1)
	{
		this->up = a;
		this->down = b;
	}
};

fra tobe_fraction(fra x)
{
	// 负数
	if(x.down < 0)
	{
		x.up *= -1;
		x.down *= -1;
	}
	// 0
	if(x.up == 0)x.down = 1;
	else // 非0就约减 
	{
		ll tmp = __gcd(abs(x.up),abs(x.down));
		x.up /= tmp;
		x.down /= tmp;
	}
	return x;
}

fra add(fra a,fra b)
{
	fra tmp;
	tmp.up = a.up*b.down + a.down*b.up;
	tmp.down = a.down*b.down;
	return tobe_fraction(tmp);
}

int main()
{
	int n;
	cin >> n ;
	
	fra ans;
	
	while(n--)
	{
		fra tmp;
//		scanf("%lld/%lld\n",&tmp.up,&tmp.down);   // scanf 不要写/n  不然会导致输入错误!!!!! 
		scanf("%lld/%lld",&tmp.up,&tmp.down);
		ans = add(ans,tmp);
	}
	ans = tobe_fraction(ans);
	if(ans.down == 1)cout << ans.up;
	else if(ans.up > ans.down)
	{
		cout << ans.up/ans.down << " " << abs(ans.up)%ans.down << "/" << ans.down;
	}
	else
	{
		cout << ans.up << "/" << ans.down;
	}
	
	return 0;
}

2 素数

1015 Reversible Primes

题目大意是一个数a必须是素数。然后将这个数a转为D进制数b,再将这个D进制数b反转成数c,将反转后的数c再转为十进制数,要求这个数依旧是素数。题目比较简单,实现判断素数、进制转换、数的反转这三个功能即可。注意特判:1不是素数!!

AC代码:

#include<iostream>

using namespace std;

bool is_prime(int x)
{
	if(x == 1)return 0;  //特判1不是素数
	
	for(int i = 2; i < x; i++)
		if(x % i == 0)return 0;
	return 1;
}

int main()
{
	while(1)
	{
		int a,b;
		cin >> a;
		if( a < 0)break;
		cin >> b;
//		cout << a << " " << b;
		
		// a是素数 
		if(!is_prime(a))
		{
			cout << "No" << endl;
			continue;
		}
		// a 转成 b 进制的数x 翻转一下 再转成10进制的y 判断是不是素数
		string x = "";
		while(a)
		{
			x += ('0' + a%b);
			a /= b;
		}
//		cout << b << "进制的" << a << "为:" << x << endl;
		
		int y = 0;
		int p = 1;
		for(int i = x.size() - 1; i >= 0; i--)
		{
			y += (x[i] - '0')*p;
			p *= b;
		}
//		cout << "y: " << y << endl;
		
		if(is_prime(y))
		{
			cout << "Yes" << endl;
		}
		else cout << "No" << endl;
		
	}
	return 0;
}

1078 Hashing

知识点:二次探测(仅具有正增量,即1^2,2^2,3^2........)用于解决碰撞。

【注意点1】step从1.....ms-1。

【注意点2】新地方 = (碰撞地方(固定的) + step^2 )%ms

AC代码:

#include<iostream>

using namespace std;

const int N = 1e4 + 10;
int t[N];
bool vis[N];

bool is_prime(int x)
{
	if(x == 1)return 0;  //特判1不是素数
	
	for(int i = 2; i < x; i++)
		if(x % i == 0)return 0;
	return 1;
}

int main()
{
	int ms,n;
	cin >> ms >> n;
	
	for(int i = 0; i < n; i++)
		cin >> t[i];
	
	while(!is_prime(ms)){ms++;}
	
	for(int i = 0; i < n; i++)
	{
		if(i != 0)cout << ' ';
		
		int tmp = t[i] % ms;
		if(!vis[tmp])
		{
			vis[tmp] = 1;
			cout << tmp;
		}
		else
		{
			int step = 1;
			int ok = 0;
			int old = tmp;
			// 发生碰撞
			for(int i = 1; i < ms; i++)   // 【注意点1】1.... ms 
			{
				if(vis[tmp])
				{
					//tmp = (tmp + step*step)%ms; 错误
					tmp = (old + step*step)%ms;  // 【注意点2】碰撞地方 + step^2
			 		step++;
				}
				else
				{
					ok = 1;
					vis[tmp] = 1;
					cout << tmp;
					break;
				}
			}
			if(ok == 0) cout << '-';
		}
	}
	
	return 0;
}

3 质因子分解

1059 Prime Factors

质因子分解的板子题目:

// 【细节1】x除的时候,for的边界是不停动态变化

 //【细节2】x有可能有且仅有一个大于根号x的质因子 

坑:特判0和1

#include<bits/stdc++.h>
using namespace std;

// 分解质因子板子题目 

typedef long long ll;

int main()
{
	ll x;
	cin >> x;
	
	int ok = 0;
	cout << x << '=';
	
	if(x <2)
	{
		cout << x ;  // 【坑】某个测试点的坑 
		return 0;
	}
	
	for(ll i = 2; i <= x / i; i++)  // 【细节1】x是不停动态变化 
	{
		if(x % i == 0)
		{
			if(ok == 1)cout << '*';
			int p = 0;
			while(x % i == 0)
			{
				x /= i;
				p++;
			}
			cout << i;
			if(p > 1)cout << '^' << p;
			ok = 1;
		}
	}
	if(x > 1)
	{
		if(ok)cout << "*" << x ;
		else cout << x;  // 【细节2	】x有可能有且仅有一个大于根号x的质因子 
	} 
	return 0;
} 

1096 Consecutive Factors

学习题解后的,我感觉难点在于看懂题目。就是找输入n的最长连续因子(这些因子乘起来小于等于n。)

AC代码:

#include<iostream>

using namespace std;

int main()
{
	int n;
	cin >> n;
	
	int l = 0;
	int len = 0;
	for(int i = 2; i <= n / i; i++)
	{
		if(n % i == 0)
		{
			int j = i;
			int n1 = n;  // 
			while(n1 % j == 0)
			{ 
				n1 /= j;  // 注意这里要把n自除掉  是n的连续因子  但是乘起来不能超过n  比如12 不能是2*3*4 
				j++;
			}
			if(j-i > len)
			{
				l = i;
				len = j - i;
			}
		}
	}
	if(len == 0)
	{
		cout<< 1 << endl  << n <<endl;
	} 
	else
	{
		cout << len << endl;
		cout << l ;
		for(int i = 1; i < len; i++)
			cout << '*' << l+i;
	}

	
	return 0;
}

总结

一个段错误常见错因

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值