CSP20230903 梯度求解满分代码

#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
typedef long long ll;

struct node
{
	char ch;
	ll num;
	int type;//0 运算 1 变量 2 表示常量
	int l, r;
} a[2000];
int n, m, cnt, dao;
int b[150];
string f;

int judge(char ch)
{
	return ch == '+' || ch == '-' || ch == '*';
}

void build()//建立表达式树
{
	istringstream ss(f);
	string temp;
	stack<int> s;
	while (ss >> temp)
	{
		//cout << "分割字符为" << temp << endl;
		if (temp.size() == 1 && judge(temp[0]))
		{
			a[cnt].type = 0;
			a[cnt].ch = temp[0];
			a[cnt].r = s.top();
			s.pop();
			a[cnt].l = s.top();
			s.pop();
			s.push(cnt);
			cnt++;
		}
		else if (temp[0] == 'x')
		{
			a[cnt].type = 1;
			a[cnt].num = stol(temp.substr(1, temp.size()));
			//cout << a[cnt].num << endl;
			s.push(cnt);
			cnt++;
		}
		else//常数
		{
			a[cnt].type = 2;
			a[cnt].num = stol(temp);
			//cout << a[cnt].num << endl;
			s.push(cnt);
			cnt++;
		}
	}
	//cout << s.size() << " " << cnt << endl;
	//cout << last << endl;
}

ll cal(int x, bool check) //计算偏导 1 求 2 原来
{
	//cout << "进入计算 " << x << endl;
	if (a[x].type == 1)
	{
		if (check)
		{
			if (dao != a[x].num)
				return 0;
			else
				return 1;
		}
		else
			return b[a[x].num];
	}
	else if (a[x].type == 2)
	{
		if (check)
			return 0;
		else
			return a[x].num;
	}
	else
	{
		ll l, r;
		if (a[x].ch == '+')
		{
			if (check)
			{
				l = cal(a[x].l, 1) % mod;
				r = cal(a[x].r, 1) % mod;
				return  (l + r) % mod;
			}

			else
				return (cal(a[x].l, 0) % mod + cal(a[x].r, 0) % mod) % mod;
		}
		else if (a[x].ch == '-')
		{
			if (check)
				return cal(a[x].l, 1) % mod - cal(a[x].r, 1) % mod;
			else
				return cal(a[x].l, 0) % mod - cal(a[x].r, 0) % mod;
		}
		else
		{
			if (check)
				return (cal(a[x].l, 1) * cal(a[x].r, 0) % mod + cal(a[x].l, 0) * cal(a[x].r, 1) % mod) % mod;
			else
				return ((cal(a[x].l, 0) % mod ) * (cal(a[x].r, 0) % mod)) % mod;
		}
	}
	return 0;
}



int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	cin >> n >> m;

	cin.ignore();
	getline(cin, f);
	build();

//	for (int i = 0; i < cnt; i++)
//	{
//		if (a[i].type == 1)
//		{
//			cout << 1 << " " << a[i].num << endl;
//		}
//		else if (a[i].type == 2)
//		{
//			cout << 2 << " " << a[i].num << endl;
//		}
//		else
//		{
//			cout << 3 << " " << a[i].ch << " " << a[i].l << " " << a[i].r << endl;
//		}
//	}
	for (int i = 0; i < m; i++)
	{
		cin >> dao;
		for (int i = 1; i <= n; i++)
			cin >> b[i];
		ll res = cal(cnt - 1, 1);
		cout << (res + mod) % mod << endl;
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值