2022 CSPJ

发布时间 2023-11-01 14:37:12作者: shirlybabyyy

 直接模拟即可,注意特判

#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define maxn 200010
#define LL long long
using namespace std;

int main()
{
    int a,b;
    cin>>a>>b;
    if(a==1){
    	cout<<1;return 0;
	}
	if(b==1){
		cout<<a;return 0;
	}
	LL ans=1;
	while(b&&ans<=1e9){
		ans*=a;
		b--;
	}
	if(ans>1e9){
		cout<<-1;return 0;
	}
	cout<<ans;
	return 0;
}

其实就是数学题,解方程而已,也可以二分因为p<q

#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define maxn 200010
#define LL long long
using namespace std;
//这道题可以用二分,也可以直接带进去式子算(一元二次方程  带公式,看算的出来不)
 
int main()
{
	LL k,n,e,d,p,q;
	cin>>k;
	while(k--){
		cin>>n>>e>>d;
		LL delta=sqrt((n-e*d+2)*(n-e*d+2)-4*n);
		LL b=n-e*d+2;
		LL p=(b+delta)/2;
		LL q=b-p;
		if(p*q==n&&e*d==(p-1)*(q-1)+1&&p&&q){
			cout<<min(p,q)<<" "<<max(p,q)<<endl;
		}
		else cout<<"NO"<<endl;
	}
	return 0;
}

 用栈把中缀转后缀表达式,在加上一些巧妙地操作。。。

 

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<queue>
#include<map>
#include<ctime>
#include<vector>
#include<set>
using namespace std;
typedef long long LL;
const int maxn=1e6+10;
using namespace std;
//表达式求值:后缀表达式
//但是有其他巧妙地操作:统计略过的计算次数 (短路)
stack<int> st;
stack<pair<int,int> > duan;  //短路或、与的次数
string s;
stack<char> op;
map<char,int> mp; //运算符优先级的 
void merg_duan(pair<int,int> aa,pair<int,int> bb,int a,int b,char p){
	//如果 a|b  a为1,那么或短路次数为a.first+1   与为aa.second 
	//如果a为0 那么就是aa+bb
	pair<int,int> c;
	if(a==1&&p=='|'){
		c.first=aa.first+1;
		c.second=aa.second;
	} 
	//如果 a&b  a为0,那么或次数不变,与次数+1 
	else if(a==0&&p=='&'){
		c=aa;
		c.second++;
	} 
	else{
		c.first=aa.first+bb.first;
		c.second=aa.second+bb.second;
	}
	duan.push(c); //把新的短路次数也加入 
}
void calc(){
	int b=st.top();st.pop();
	int a=st.top();st.pop();
	int num=0;
	pair<int,int> bb=duan.top();duan.pop();
	pair<int,int> aa=duan.top();duan.pop();
	merg_duan(aa,bb,a,b,op.top());
	if(op.top()=='|') num=a|b;
	else if(op.top()=='&') num=a&b;
	st.push(num);
	op.pop();
	return; 
	
}
void solve(){
	int len=s.length();
	for(int i=0;i<len;i++){
		if(isdigit(s[i])) st.push(s[i]-'0'),duan.push({0,0});
		//遇到数字,就入栈,数字和短路次数
		else{
			if(s[i]=='(') op.push('(');
			if(s[i]==')'){
				while(!op.empty()&&op.top()!='(') calc();
				if(!op.empty()) op.pop(); //把(弹出去 
			}
			if(s[i]!='('&&s[i]!=')'){
				//如果遇到运算符,就先把栈里面优先级高的都弹出 
				while(!op.empty()&&mp[op.top()]>=mp[s[i]]) calc();
				op.push(s[i]);
			}
		} 
	}
	while(!op.empty()){
		calc();
	}
	cout<<st.top()<<endl<<duan.top().second<<" "<<duan.top().first<<endl;
}
int main(){
	cin>>s;
	mp['&']=2;
	mp['|']=1;	
	solve();
	return 0;
}

  

 典型的dp

f[i][j]表示走到i,用了插入的j个点能取到的最大值

#include <bits/stdc++.h>
using namespace std;
const int maxn=505;
int f[maxn][maxn];   //f[i][j]: 前 i 个点,插入了 j 个点后最大长度
pair<int,int> a[maxn];
int main()
{
	int n,k;
	cin>>n>>k;
	for(int i=1;i<=n;i++) cin>>a[i].first>>a[i].second;
	sort(a+1,a+1+n);
	for(int i=1;i<=n;i++){
		for(int j=0;j<=k;j++) f[i][j]=1+j;
	}
	//最长上升子序列
	for(int i=2;i<=n;i++){
		for(int j=i-1;j>=1;j--){
			if(a[j].second>a[i].second) continue;
			//从j到i要插入d个点
			int d=a[i].first-a[j].first+a[i].second-a[j].second-1;
			for(int p=d;p<=k;p++) f[i][p]=max(f[i][p],f[j][p-d]+1+d); 
		}
	} 
	int ans=0;
	for(int i=1;i<=n;i++) ans=max(ans,f[i][k]);
	cout<<ans<<endl;
	return 0;
}