2022 CSP-J2 自测有感

前言

模拟只会猜题意,贪心只能过样例。
数学上来先打表,规律一般是DP。
递归递推伤不起,搜索茫然TLE。
分治做得像枚举,快排冒泡数第一。
数据结构干瞪眼,怒刷水题找信心。

--借鉴于某Z姓同学写的打油诗

 

话说天下大势,变幻莫测,出没无常。去年十月信奥兴起,本蒟蒻遂报名而学之,而来一年有一月矣。十月二十九虽是予考试之日,然疫情肆虐,十数省无奈取消竞赛,湖北亦在其中。呜呼哀哉!予心中悲愤,自测之后感慨万分,遂记题解于文档之中。如有疏忽,万望赐教。

2022 CSP-J2 自测有感_第1张图片

 

题目可在https://www.luogu.com.cn/contest/90215中查到

注:T3、T4的代码是在网上查到的 (主要是本蒟蒻代码写的非常之烂,我的老师说过我的代码可读性极差)

 

 

T1 乘方

水题一道,循环相乘,超过1e9输出-1退出循环即可。

注:特判情况a=1,否则会超时!!!

代码如下(这题代码不会有人要抄吧):

//pow
#include
using namespace std;
long long a,b,sum=1;
const long long int all=1000000000;
int main()
{
	//freopen("pow.in","r",stdin);
	//freopen("pow.out","w",stdout);
	scanf("%lld%lld",&a,&b);
	if(a==1){
		printf("1\n");
		return 0;
	}
	for(int i=0;iall){
			printf("-1\n");
			return 0;
		}
	}
	printf("%lld\n",sum);
	return 0;
}

/*
10 9

23333 66666

*/

 

 

T2 解密

十年OI一场空,不开long long见祖宗

50-60分方法:暴力枚举,就不用多说了吧。。。

 

满分方法:

这道题对xxs及其不友好,因为涉及到了一元二次方程求根式。

为啥呢?我们来推一推题面中n=p*q,e*d=(p-1)(q-1)+1这两个式子。

解:e*d=(p-1)*(q-1)+1

e*d=p*q-p-q+2

e*d=p*q-p-n/p(因为n=pq)+2

e*d*p=p*p*q-p*p-n+2*p

e*d*p-p*p*q+p*p+n-2*p=0

p*p+(e*d-n-2)*p+n=0

显然这是一个关于p,q的一元二次方程组,直接求解+特判(p,q为正整数,p<=q,△>=0)就应该可以AC了。民间数据AC代码如下:

//decode
#include
using namespace std;
int k;
long long n,d,e;
int main()
{
	//freopen("decode.in","r",stdin);
	//freopen("decode.out","w",stdout);
	scanf("%d",&k);
	while(k--){
		scanf("%lld%lld%lld",&n,&d,&e);
		long long a=1,b=e*d-n-2,c=n;
		long long delta=b*b-4*a*c;
		long long d=sqrt(delta);
		if(delta<0 || (b-d)%2!=0 || d*d!=delta){
			printf("NO\n");
			continue;
		}
		long double p1=(-b+sqrt(delta))/(2.0*a);
		long double p2=(-b-sqrt(delta))/(2.0*a);
		long double q1=n/p1,q2=n/p2;
		long long p,q;
		if(p1>0){
			p=long(p1); q=long(q1);
			if(p*q==n){
				if(q0){
			p=long(p2); q=long(q2);
			if(p*q==n){
				if(q

 

 

T3 逻辑表达式

一道较为恶心的模拟(算是),如果打表应该能骗前四个测试点(EMM...)。

满分方法:

进行模拟,可以建三个栈,分别储存0或1、|或&、短路次数。遇到数字正常入栈,遇到反括号时,将栈内与之匹配正括号之间的数进行计算。
遇到|或&将站内优先级相等或更高的符号先进行运算求值,再入栈。
对于短路次数计算,短路操作只有a&b -> a=0. a|b -> a==1。
对于每一个表达式,可以设三个变量,分别为表达式的值、&短路次数、|短路次数。看代码就得了:

//expr
#include
using namespace std;
stack num;
stack op;
stack > c;
pair c1,c2;
string s;
int getP(char p){
	if(p=='&'){
		return 2;
	}
	if(p=='|'){
		return 1;
	}
	if(p=='('){
		return 0;
	}
}
void cal(){
	int n1=num.top();
	c1=c.top();
	num.pop();
	c.pop();
	
	int n2=num.top();
	c2=c.top();
	num.pop();
	c.pop();
	
	char p=op.top();
	op.pop();
	
	if(p=='&'){
		num.push(n1&n2);
		if(n2==0){
			c.push({c2.first+1,c2.second});
		}
		else{
			c.push({c1.first+c2.first,c1.second+c2.second});
		}
	}
	else if(p=='|'){
		num.push(n1|n2);
		if(n2==1){
			c.push({c2.first,c2.second+1});
		}
		else{
			c.push({c1.first+c2.first,c1.second+c2.second});
		}
	}
}
int main()
{
	//freopen("expr.in","r",stdin);
	//freopen("expr.out","w",stdout);
	cin>>s;
	int tmp=0;
	for(int i=0;i0 && getP(op.top())>=getP(s[i])){
					cal();
				}
				op.push(s[i]);
			}
		}
		
	}
	while(op.size()>0){
		cal();
	}
	cout<

 

 

T4 上升点列

满分方法:

  1. 动态规划(不会)
  2. 用记忆化搜索,dfs函数的参数分别是以u点开头还剩下temp个可添加点的最大长度,代码如下:
//point
#include
using namespace std;
int n,k,maxn,p[650][650];
struct node{
	int x,y;
}a[650];
bool cmp(node xx,node yy){
	if(xx.x!=yy.x) return xx.xtemp){
				continue;
			}
			else if(a[i].x

 

 

后记

个人感觉比去年难,但网上大多说比去年简单。

管他呢,我都考不了(悲)。

Anyway, 在最后, 还是祝大家rp++, 希望疫情早些结束, NOIp 2022再战!

 

你可能感兴趣的:(c++)