梯度求解csp

本文介绍了如何使用C++处理逆波兰表达式,通过替换自变量和非自变量,利用栈进行运算,最终求导并输出结果。提到代码仅能得到80分,可能是因为数据范围和边界条件的限制。
摘要由CSDN通过智能技术生成

1.解题思路

对于输入一个逆波兰表达式,首先将除自变量之外的其他变量用对应的数值替换,自变量统一用’x‘进行替换,然后用栈处理逆波兰表达式,遇到运算符就取出栈顶两个数做相应运算并将结果压栈,非运算符直接压栈,用变长数组vector保存结果,数组下标表示指数,值表示系数,例如对于x^3+x,可以表示为v[0]=0,v[1]=1,v[2]=0,v[3]=1,最后进行求导将自变量的值带入,每个部分指数乘系数再加起来得到最终结果。

不过真的不太清楚为什么只有80,数据范围、取模都考虑到了但是还是只有80QAQ,累了就这样吧。。。

2.80分代码

//csp是不是数据增强了?? 
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const long long mod=1e9+7;
ll n,m;
vector<string>replacex(vector<string>f,ll xi,vector<ll>xs)//将除自变量外的变量用其值代替 
{
	ll len=f.size();
	vector<string>res;
	for(ll i=0;i<len;i++)
	{
		if(f[i][0]=='x')
		{
			ll x=stoll(f[i].substr(1,f[i].size()-1));
			if(x==xi)
			{
				res.push_back("x");
			}
			else
			{
				res.push_back(to_string(xs[x-1]));
			}
		}
		else
		res.push_back(f[i]);
	}
	return res;
}
vector<ll>cal(vector<ll>v1,vector<ll>v2,string op)//对两个数组进行加、减、乘操作 
{
	vector<ll>res;
	if(op=="+")
	{
		ll len1=v1.size();
		ll len2=v2.size();
		res.resize(max(len1,len2));
		for(ll i=0;i<res.size();i++)
		{
			ll x1=0,x2=0;
			if(i<len1)x1=v1[i];
			if(i<len2)x2=v2[i];
			res[i]=x1+x2;
		}
	}
	else if(op=="-")
	{
		ll len1=v1.size();
		ll len2=v2.size();
		res.resize(max(len1,len2));
		for(ll i=0;i<res.size();i++)
		{
			ll x1=0,x2=0;
			if(i<len1)x1=v1[i];
			if(i<len2)x2=v2[i];
			res[i]=x1-x2;
		}
	}
	else if(op=="*")
	{
		ll len1=v1.size();
		ll len2=v2.size();
		ll len=len1+len2-1;
		res.resize(len);
		for(ll i=0;i<len1;i++)
		{
			for(ll j=0;j<len2;j++)
			{
				res[i+j]+=v1[i]*v2[j];
			}
		}
	}
	return res;
}
vector<ll>bolan(vector<string>f)//逆波兰表达式求解 数组下标表示指数 值表示系数 
{
	stack<vector<ll>>s;
	ll len=f.size();
	for(ll i=0;i<len;i++)
	{
		if(f[i]=="+")
		{
			vector<ll>v1=s.top();
			s.pop();
			vector<ll>v2=s.top();
			s.pop();
			s.push(cal(v1,v2,"+"));
		}
		else if(f[i]=="-")
		{
			vector<ll>v1=s.top();
			s.pop();
			vector<ll>v2=s.top();
			s.pop();
			s.push(cal(v2,v1,"-"));
		}
		else if(f[i]=="*")
		{
			vector<ll>v1=s.top();
			s.pop();
			vector<ll>v2=s.top();
			s.pop();
			s.push(cal(v1,v2,"*"));
		}
		else
		{
			if(f[i]=="x")
			s.push({0,1});
			else
			s.push({stoll(f[i])});
		}
	}
	return s.top();
}
ll daoshu(vector<ll>v,ll x)
{
	ll len=v.size();
	ll res=0;
	for(ll i=0;i<len-1;i++)
	{
		res+=((v[i+1]*(i+1))%mod)*pow(x,i);
		res%=mod;
		if(res<0)res+=mod;
	}
	return res;
}
int main()
{
	cin>>n>>m;
	string tmp;
    vector<string>ans;
	cin.ignore();
	getline(cin,tmp);
	stringstream ss(tmp);
	while(ss>>tmp)ans.emplace_back(tmp);
	while(m--)
	{
		ll xi,ai;
		vector<ll>xs;
		cin>>xi;
		for(ll i=0;i<n;i++)
		{
			cin>>ai;
			xs.emplace_back(ai);
		}
		vector<string>nf=replacex(ans,xi,xs);
		vector<ll>tmpans=bolan(nf);
		ll res=daoshu(tmpans,xs[xi-1]);
		res=res%mod;
		if(res<0)res+=mod;
		cout<<res<<endl;
	}
	return 0;
} 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值