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