目录
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;
}