CCF计算机软件能力认证考试2023-09

目录

202309-1:坐标变换(其一)

202309-2:坐标变换(其二)

202309-3:梯度求解

202309-4:阴阳龙

提交记录:


202309-1:坐标变换(其一)

思路:

        只需对平移操作序列中的x和y分别求和,可以得到最终x和y平移的距离,对于每次查询直接分别加上平移距离即可。

代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n,m,ddx=0,ddy=0;
	cin >>n>>m;
	for(int i=1;i<=n;i++)
	{
		int dx,dy;
		cin >>dx>>dy;
		ddx+=dx,ddy+=dy;
	}
	for(int i=1;i<=m;i++)
	{
		int x,y;
		cin >>x>>y;
		cout <<x+ddx<<" "<<y+ddy<<endl;
	}
	return 0;
}

202309-2:坐标变换(其二)

思路:

       优化思路和第一题差不多,可以发现坐标变化之间的叠加性和叠乘性,而且拉伸和旋转互不影响,因此可以计算操作序列区间内一共旋转了多少,一共拉伸了多少,那么就可以想到前缀和和前缀乘来求解。

代码:

#include<bits/stdc++.h>
#define N 200000
using namespace std;
double s[N],c[N];
int main()
{
	int n,m,op;
	double k;
	cin >>n>>m;
	for(int i=0;i<=n;i++) s[i]=1;
	for(int i=1;i<=n;i++)
	{
		cin >>op>>k;
		if(op==1)
		{
			s[i]=k;
		}else{
			c[i]=k;
		}
	}
	for(int i=1;i<=n;i++)
	{
		s[i]*=s[i-1];
		c[i]+=c[i-1];
		//cout <<s[i]<<" "<<c[i]<<endl;
	}
	for(int i=1;i<=m;i++)
	{
		int l,r;
		double x,y;
		cin >>l>>r>>x>>y;
		double dk=s[r]/s[l-1],dc=c[r]-c[l-1];
		double dx=dk*(x*cos(dc)-y*sin(dc)),dy=dk*(x*sin(dc)+y*cos(dc));
		printf("%.3f %.3f\n",dx,dy);
	}
	return 0;
}

202309-3:梯度求解

思路:

先利用栈将后缀表达式转化成中缀表达式:

        1.对于乘法将连乘的数看做一个整体。

        2.对于加法直接取出栈顶两个元素然后连接起来入栈即可。

        3.对于减法,取出两个栈顶元素后还要将后面元素中的符合变号。(一直卡在这里)

        4.多项式乘多项式,注意符号的变化。

计算偏导值:

        1.只需要找到含要求偏导数的自变量的式子即可,然后对其出现次数计数,模拟求偏导。

        2.注意符号。

        3.注意取模。

代码:

#include<bits/stdc++.h>
#define N 2000000
#define int long long
#define pb push_back
using namespace std;
const int mod=1e9+7;
int n,a[N],b[N];
stack<vector<string>>f;
vector<string>op;
void solve()
{
	for(int i=0;i<op.size();i++)
	{
		int cnt=0;
		if(op[i]!="+"&&op[i]!="-")
		{
			for(int j=0;j<op[i].size();j++)
			{
				int k=op[i].find("x",j);
				if(k!=-1)
				{
					int kk=k+1,num=0;
					while(kk<op[i].size()&&op[i][kk]>='0'&&op[i][kk]<='9')
					{
						num=num*10+op[i][kk]-'0';kk++;
					}
					j=kk-1;
					if(num==a[0]) cnt++;
				}else{
					break;
				}
			}
		}
		b[i]=cnt;
	}
	// for(int i=0;i<op.size();i++)
	// {
		// cout <<b[i]<<" ";
	// }
	// cout <<endl;
	int ans=0,tt=0;
	for(int i=0;i<op.size();i++)
	{
		if(op[i]=="+") tt=0;
		if(op[i]=="-") tt=1;
		if(op[i]!="+"&&op[i]!="-")
		{
			if(b[i]!=0)
			{
				int res=b[i];
				for(int j=0;j<op[i].size();j++)
				{
					//cout <<j<<"bug"<<endl;
					int k=op[i].find("*",j);
					if(k!=-1)
					{
						string st=op[i].substr(j,k-j);
						if(st.front()=='x'){
							st.erase(st.begin());
							int num=stoi(st);
							//cout <<num<<endl;
							if(num==a[0])
							{
								if(b[i]>1)res=(res*a[num]%mod+mod)%mod;
								b[i]--;
							}else{
								res=(res*a[num]%mod+mod)%mod;
							}
						}else{
							int num=stoi(st);
							res=(res*num%mod+mod)%mod;
						}
						j=k;
					}else{
						string st=op[i].substr(j);
						if(st.front()=='x'){
							st.erase(st.begin());
							int num=stoi(st);
							//cout <<num<<endl;
							if(num==a[0])
							{
								if(b[i]>1)res=(res*a[num]%mod+mod)%mod;
								b[i]--;
							}else{
								res=(res*a[num]%mod+mod)%mod;
							}
						}else{
							int num=stoi(st);
							res=(res*num%mod+mod)%mod;
						}
						break;
					}
				}
				//cout <<res<<endl;
				if(tt) ans=(ans%mod-res%mod+mod)%mod;
				else ans=(ans%mod+res%mod+mod)%mod;
			}
		}
	}
	cout <<ans<<endl;
}
void check(string st)
{
	vector<string>l,r,res;
	if(st=="+"||st=="-")
	{
		r=f.top();f.pop();
		l=f.top();f.pop();
		for(auto it : l) res.pb(it);
		res.pb(st);
		for(auto it : r)
		{
			if(it=="+"||it=="-")
			{
				if(it!=st)
				{
					res.pb("-");
				}else{
					res.pb("+");
				}
			}else{
				res.pb(it);
			}
		}
	}else if(st=="*")
	{
		r=f.top();f.pop();
		l=f.top();f.pop();
		int op1=0,op2=0;
		string s1,s2;
		for(int i=0;i<l.size();i++)
		{
			if(l[i]=="+"||l[i]=="-")
			{
				if(l[i]=="+") op1=0;
				else op1=1;
				s1="";	
			}else{
				s1=l[i];
			}
			for(int j=0;j<r.size();j++)
			{
				if(j==0) op2=0;
				if(r[j]=="+"||r[j]=="-")
				{
					if(r[j]=="+") op2=0;
					else op2=1;
					s2="";
				}else{
					s2=r[j];
				}
				if((i!=0||j!=0)&&s1!=""&&s2!="")
				{
					if(op1^op2)
					{
						res.pb("-");
					}else{
						res.pb("+");
					}
				}
				if(s1!=""&&s2!="") res.pb(s1+"*"+s2);
			}
		}
	}else{
		res.pb(st);
	}
	f.push(res);
}
signed main()
{
	int q;
	string str,st;
	cin >>n>>q;
	getline(cin,str);
	getline(cin,str);
	//cout <<str<<endl;
	for(int i=0;i<str.size();i++)
	{
		int j=str.find(' ',i);
		if(j!=-1)
		{
			st=str.substr(i,j-i);
			check(st);
			i=j;
		}else{
			st=str.substr(i);
			check(st);
			break;
		}
		//cout <<st<<endl;
	}
	op=f.top();
	// for(auto it : op)
	// {
		// cout <<it<<endl;
	// }
	while(q--)
	{
		for(int i=0;i<=n;i++)
		{
			cin >>a[i];
		}
		solve();
	}
	return 0;
}

202309-4:阴阳龙

思路:

        首先看懂题意!!!

        1.对于阴阳龙移动的八个方向,按照斜率分为四类,然后以斜率为键存储在map中,值用set表示,便于后续查找最近位置(要用set自带的二分查找,不能用std的二分查找)。

        2.求出阴阳龙到员工的最小距离和到边界的最小距离,如果到员工的最小距离小于等于到边界的最小距离,那么可能有员工位置的改变(注意关于set的二分查找和迭代器的位置移动)。

        3.对于变化位置的员工,可以先移除,并记录下一个位置和哪个点被移除,移除完之后,再添加上改变位置后的点。

        4.计算结果,记得开long long,int会溢出。

代码:

#include<bits/stdc++.h>
//#define int long long
#define N 200000
#define pb push_back
#define fi first
#define se second
#define PII pair<int,int>
using namespace std;
const int inf=((long long)1<<31)-1;
int dx[]={1,1,0,-1,-1,-1,0,1},dy[]={0,1,1,1,0,-1,-1,-1};
int n,m;
map<int,set<int>>row,col,lk,rk;
map<PII,int>v;
void insert_(int x,int y)
{
	row[x].insert(y);
	col[y].insert(x);
	lk[x+y].insert(x);
	rk[x-y].insert(x);
}
void delete_(int x,int y)
{
	row[x].erase(y);
	col[y].erase(x);
	lk[x+y].erase(x);
	rk[x-y].erase(x);
}
int check1(int x,int y,map<int,set<int>>& op)
{
	int ans=inf;
	if(op[x].size())
	{
		auto id=op[x].lower_bound(y);
		if(id==op[x].end())
		{
			ans=min(ans,abs(y-*(--id)));
		}else{
			if(*id==y)
			{
				if(id!=op[x].begin())
				{
					ans=min(ans,abs(y-*(--id)));
					++id;
				}
				if(++id!=op[x].end())
				{
					ans=min(ans,abs(y-*id));
				}
			}else{
				if(id!=op[x].begin())
				{
					ans=min(ans,abs(y-*(--id)));
					++id;
				}
				ans=min(ans,abs(y-*(id)));
			}
		}
	}
	return ans;
}
int check2(int x,int y,map<int,set<int>>& op)
{
	int ans=inf;
	if(op[x-y].size())
	{
		auto id=op[x-y].lower_bound(x);
		if(id==op[x-y].end())
		{
			ans=min(ans,abs(x-*(--id)));
		}else{
			if(*id==x)
			{
				if(id!=op[x-y].begin())
				{
					ans=min(ans,abs(x-*(--id)));
					++id;
				}
				if(++id!=op[x-y].end())
				{
					ans=min(ans,abs(x-*id));
				}
			}else{
				if(id!=op[x-y].begin())
				{
					ans=min(ans,abs(x-*(--id)));
					++id;
				}
				ans=min(ans,abs(x-*(id)));
			}
		}
	}
	return ans;
}                                                                
int main()
{
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	int p,q;
	cin >>n>>m>>p>>q;
	for(int i=1;i<=p;i++)
	{
		int x,y;
		cin >>x>>y;
		v[{x,y}]=i;
		insert_(x,y);
	}
	for(int i=1;i<=q;i++)
	{
		int x,y,t;
		cin >>x>>y>>t;
		int ma=min({n-x,m-y,x-1,y-1}),mi=inf;
		//cout <<mi<<endl;
		mi=min(check1(x,y,row),mi);
		//cout <<mi<<endl;
		mi=min(check1(y,x,col),mi);
		//cout <<mi<<endl;
		mi=min(check2(x,-y,lk),mi);
		//cout <<mi<<endl;
		mi=min(check2(x,y,rk),mi);
		//cout <<mi<<endl;
		if(mi<=ma)
		{
			//cout <<mi<<endl;
			int l,r;
			vector<PII>res1;
			vector<int>res;
			for(int j=0;j<8;j++)
			{
				l=x+mi*dx[j],r=y+mi*dy[j];
				if(l>=1&&r>=1&&l<=n&&r<=m&&row[l].lower_bound(r)!=row[l].end()&&*row[l].lower_bound(r)==r)
				{
					int lx=x+mi*dx[(j+t)%8],rx=y+mi*dy[(j+t)%8];
					if(lx>=1&&rx>=1&&lx<=n&&rx<=m)
					{
						res1.pb({lx,rx});
						res.pb(v[{l,r}]);
						v[{l,r}]=0;
						delete_(l,r);
					}
				}
			}
			int len=res1.size();
			for(int j=0;j<len;j++)
			{
				//cout <<res1[j].fi<<" "<<res1[j].se<<" "<<res[j]<<endl;
				v[{res1[j].fi,res1[j].se}]=res[j];
				insert_(res1[j].fi,res1[j].se);
			}
		}
	}
	long long ans=0;
	for(auto it : v)
	{
		if(it.se>0)
		{
			//cout <<it.se<<" "<<(it.fi).fi<<" "<<(it.fi).se<<endl;
			//cout <<((it.fi).fi*it.se+(it.fi).se)<<endl;
			ans^=((long long)(it.fi).fi*it.se+(it.fi).se);
		}
	}
	cout <<ans<<endl;
	return 0;
}

提交记录:

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值