CFF2023年9月梯度求,个人思路和代码请求大佬指正

        这一题的主要考点呢是 字符串的操作和对栈的使用(其实就是一个逆波兰表达式)并且对求导公式能够进行一些变形

          1、这一部分呢主要是对给定的字符串去掉空格,然后再将字符串通过空格将每一项存入到字符串数组

vector<string> get_str(string s)  
{   
    vector<string> re;
    stringstream ssin(s);
    while (ssin >> s)
    {
        re.push_back(s);
    }

    return re;
}

 2、因为是求偏导所以除了需要求的变量以外其实都是常数,这里直接就进行替换了

vector <string> getni(vector<string> s , int x)
{
    vector <string> tmp;
    for (int i = 0; i < s.size(); i++)
    {
        //如果含有x
        if (s[i][0] == 'x')
        {
            if (xi[0] != stoll(s[i].substr(1).c_str()))  //stoll函数的作用是将字符串转换为数字
            {
                int n = stoll(s[i].substr(1).c_str());
                tmp.push_back(to_string(xi[n]));
            }
            else
            {
                tmp.push_back("x");
            }
        }
        else
        {
            tmp.push_back(s[i]);
        }
    }

    return tmp;
}

3、第三步也就是核心的思路了

用一个例子来举例  x1 x2 * + x1   输入1 2 3

经过前面两步之后呢变成了 s = {x ,3, *, +, x} 存在字符串数组里面

map<LL , int> re; 中re[0]表示导数的值 re[1]表示多项式的值

1、那么第一步扫描发现了 x则将<1 , x>的值入栈

2、第二步发现了"3"那么将<0 , 3>入栈

3、第二步发现了" * "那么将<0 , 3>,<1 , x>出栈后面 ,后出栈的再操作符左边而后将

< 0*x + 3*1 ,3*x >入栈

//用哈希表栈来同时维护表达式和求导表达式  表达式结束的时候求导也结束了
LL Derivation(vector<string> tmp ,int x)
{
    stack<map<int, LL> > result;

    for (int i = 0; i < tmp.size(); i++)
    {
        if (tmp[i][0] == 'x')
        {
            map<int , LL> p;
            p[0] = 1;                  //表示x的导数的式子
            p[1] = x;
            result.push(p);
        }
        else if (isdigit(tmp[i][0]))
        {
            map<int, LL> p;
            p[0] = 0;
            p[1] = stoll(tmp[i]);
            result.push(p);
        }
        else if (tmp[i][0] == '+'&& result.size() >= 2)
        {

            map<int, LL> p;
            map<int, LL> pre = result.top(); result.pop();
            map<int, LL> suf = result.top(); result.pop();
            //加法求导之后的结果
            p[0] = ((suf[0] + pre[0])%N + N) % N;
            p[1] = ((suf[1] + pre[1]) % N + N) % N;
            result.push(p);
        }
        else if (tmp[i][0] == '-' && tmp[i].size() == 1 && result.size() >= 2)
        {
            map<int, LL> p;
            map<int, LL> pre = result.top(); result.pop();
            map<int, LL> suf = result.top(); result.pop();
            //加法求导之后的结果
            p[0] = ((suf[0] - pre[0]) % N + N) % N;
            p[1] = ((suf[1] - pre[1]) % N + N) % N;
            result.push(p);
        }
        else if (tmp[i][0] == '*' && result.size() >= 2)
        {
            map<int, LL> p;
            map<int, LL> pre = result.top(); result.pop();
            map<int, LL> suf = result.top(); result.pop();
            //加法求导之后的结果
            p[0] = ((suf[1] * pre[0] + suf[0] * pre[1])%N+N) % N;
            p[1] =( (suf[1] * pre[1]) % N  +  N)%N;  //乘法求导
            result.push(p);
        }
        else if(tmp[i][0] == '-')
        {
            map<int, LL> p;
            p[0] = 0;
            p[1] = stoll(tmp[i]);
            result.push(p);
        }
    }

以下便是完整代码

#include<iostream> 
#include<cstring>
#include<algorithm>
#include<sstream>
#include<vector>
#include<stack>
#include<map>

using namespace std;
typedef long long LL;
vector<string> str;  //存储表达式
const int N = 1e9 + 7;
int xi[110];

//处理字符串  将字符串通过空格拆分到vector<string>数组里面去
vector<string> get_str(string s)  
{   
    vector<string> re;
    stringstream ssin(s);
    while (ssin >> s)
    {
        re.push_back(s);
    }

    return re;
}

//将字符串数组中的非变量全部转换为数字 字符串 除了操作符
vector <string> getni(vector<string> s , int x)
{
    vector <string> tmp;
    for (int i = 0; i < s.size(); i++)
    {
        //如果含有x
        if (s[i][0] == 'x')
        {
            if (xi[0] != stoll(s[i].substr(1).c_str()))
            {
                int n = stoll(s[i].substr(1).c_str());
                tmp.push_back(to_string(xi[n]));
            }
            else
            {
                tmp.push_back("x");
            }
        }
        else
        {
            tmp.push_back(s[i]);
        }
    }

    return tmp;
}


//用哈希表栈来同时维护表达式和求导表达式  表达式结束的时候求导也结束了
LL Derivation(vector<string> tmp ,int x)
{
    stack<map<int, LL> > result;

    for (int i = 0; i < tmp.size(); i++)
    {
        if (tmp[i][0] == 'x')
        {
            map<int , LL> p;
            p[0] = 1;                  //表示x的导数的式子
            p[1] = x;
            result.push(p);
        }
        else if (isdigit(tmp[i][0]))
        {
            map<int, LL> p;
            p[0] = 0;
            p[1] = stoll(tmp[i]);
            result.push(p);
        }
        else if (tmp[i][0] == '+'&& result.size() >= 2)
        {

            map<int, LL> p;
            map<int, LL> pre = result.top(); result.pop();
            map<int, LL> suf = result.top(); result.pop();
            //加法求导之后的结果
            p[0] = ((suf[0] + pre[0])%N + N) % N;
            p[1] = ((suf[1] + pre[1]) % N + N) % N;
            result.push(p);
        }
        else if (tmp[i][0] == '-' && tmp[i].size() == 1 && result.size() >= 2)
        {
            map<int, LL> p;
            map<int, LL> pre = result.top(); result.pop();
            map<int, LL> suf = result.top(); result.pop();
            //加法求导之后的结果
            p[0] = ((suf[0] - pre[0]) % N + N) % N;
            p[1] = ((suf[1] - pre[1]) % N + N) % N;
            result.push(p);
        }
        else if (tmp[i][0] == '*' && result.size() >= 2)
        {
            map<int, LL> p;
            map<int, LL> pre = result.top(); result.pop();
            map<int, LL> suf = result.top(); result.pop();
            //加法求导之后的结果
            p[0] = ((suf[1] * pre[0] + suf[0] * pre[1])%N+N) % N;
            p[1] =( (suf[1] * pre[1]) % N  +  N)%N;  //乘法求导
            result.push(p);
        }
        else if(tmp[i][0] == '-')
        {
            map<int, LL> p;
            p[0] = 0;
            p[1] = stoll(tmp[i]);
            result.push(p);
        }
    }

    LL re_L = result.top()[0];
    return re_L;
}


int main()
{
    int n, m;  //读取写入的未知量个数 和 操作次数
    string s;
    vector<LL> result;
    cin >> n >> m;
    getchar(); //读取'\n'
    getline(cin , s);  //读取表达式
    str = get_str(s);
    //表示操作了多少次
    while (m--)
    {
        vector<string> tmp;  //作为一个中间变量
        for (int i = 0; i <= n ; i++)
        {
            int x;
            scanf_s("%d" , &x);
            xi[i] = x;
        }
        int x = xi[xi[0]];  //这个x表示的未知量下标
        tmp = getni(str  , x);
        LL k = Derivation(tmp, x);
        result.push_back(k);
    }
    
    for (int i = 0; i < result.size(); i++)
    {
        LL r = result[i];
        r = ((r % N) + N) % N;
        cout << r << endl;
    }
    
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值