csp 202309-3 梯度求解 c++(模拟)

 关键:构造可以存储多项式的数据结构

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll mod=1e9+7;
int n, m;
vector<ll> val;
struct item //多项式
{
    ll coe; //系数
    map<int, int> mp; //下标为key,指数为val
    item(ll coe,map<int, int> mp) : coe(coe),mp(mp){} //构造体函数
};
struct formula //加号连接的多个多项式的公式
{
    vector<item> vec; //多项式数组
    formula(vector<item> vec) : vec(vec){} //构造体函数
};
stack<formula> st; //栈

item item_mul(item a, item b) //各变量拼接成多项式
{
    ll coe = a.coe * b.coe;
    map<int, int> mp;
    for(auto it : a.mp)
    {
        mp[it.first] = a.mp[it.first] + b.mp[it.first];
        b.mp.erase(it.first);
    }
    for(auto it : b.mp)
    {
        mp[it.first] = b.mp[it.first];
    }
    return item(coe, mp);
}

formula formula_mul(formula a, formula b) //多项式乘法
{
    vector<item> vec;
    for(int i = 0; i < a.vec.size(); i++)
    {
        for(int j = 0; j < b.vec.size(); j++)
        {
            vec.push_back(item_mul(a.vec[i], b.vec[j]));
        }
    }
    return formula(vec);
}
formula formula_add(formula a, formula b)  //多项式加法
{
    for(int i = 0; i < b.vec.size(); i++)
    {
        a.vec.push_back(b.vec[i]);
    }
    return a;
}
formula formula_sub(formula a, formula b) //多项式减法
{
    for(int i = 0; i < a.vec.size(); i++)
    {
        a.vec[i].coe *= -1;
    }
    return formula_add(b, a);
}
ll func(formula a, int goal) //求偏导
{
    ll sum = 0, mul = 1;
    for(int i = 0; i < a.vec.size(); i++)
    {
        item t = a.vec[i];
        mul = 1;
        if(t.mp.find(goal) != t.mp.end()) //包含求偏导的变量的多项式,否则无意义
        {
            mul = (t.coe * t.mp[goal]) % mod; //系数
            t.mp[goal]--; //指数
            for(auto it : t.mp) //每个变量赋值
            {
                for(int j = 0; j < it.second; j++) //指数为j,乘j次
                {
                    mul = (mul * val[it.first]) % mod;
                }
            }
            sum = (sum + mul) % mod; //求和
        }
    }
    return sum;
}

/*
ll convert(string str)
{
	ll num=0;
	for(int i=(str[0]=='-')?1:0;i<str.length();i++){
		num*=10;
		num+=str[i]-'0';
	}
	return (str[0]=='-')?-1*num:num;
}
*/
int main()
{
    cin >> n >> m;
    getchar();
    string str, s;
    getline(cin, str);
    stringstream sin(str); //将str中的字符串取出到s(按每个空格)
    while(sin >> s)
    {
        if(s == "+" || s == "-" || s == "*") //符号op,取出两个数作b op a
        {
            formula a = st.top();st.pop();
            formula b = st.top();st.pop();
            if(s == "*")
            {
                st.push(formula_mul(b,a));
            }
            else if(s == "+")
            {
                st.push(formula_add(b, a));
            }
            else
            {
                st.push(formula_sub(a, b));
            }
        }
        else
        {
            map<int, int> mp;
            vector<item> vec;
            if(s[0] == 'x')   //变量,取出下标,指数为1
            {
                s = s.substr(1);
                mp[stol(s)] = 1;
                //mp[convert(s.substr(1,s.length()-1))]=1;
                vec.push_back(item(1, mp));
            }
            else //常数,下标和指数均为0
            {
                vec.push_back(item(stol(s), mp));
                //vec.push_back(item(convert(s),mp));
            }
            st.push(formula(vec));
        }
    }
    for(int i = 0; i < m; i++)
    {
        ll v;
        for(int j = 0; j < n + 1; j++) //第一个为求偏导的变量,后面为变量的值
        {
            cin >> v;
            val.push_back(v);
        }
        ll ans = func(st.top(), val[0]); //栈顶剩余的最后一个公式为最终公式式,对val[0]求偏导
        cout << ((ans < 0) ? ans + mod : ans) << endl; //负数要转化为正数
        val.clear();
    }
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Patrickstarԅ(¯ㅂ¯ԅ)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值