55分,两个点没过(其实是一个,那两个数据好像一样),有没有大佬发一下代码也行啊
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=998244353;
ll qpow(ll a,ll b,int mod){
a%=mod;
ll res=1;
for (;b;b>>=1,a=a*a%mod) if (b&1) res=res*a%mod;
return res;
}
ll phi(ll x){
ll ans=x;
for (ll i=2;i*i<=x;i++){
if (x%i==0){
ans=ans/i*(i-1);
do{
x/=i;
}while (x%i==0);
}
}
if (x>1) ans=ans/x*(x-1);
return ans;
}
int _phi[]={998244353,998244352,402653184,134217728,67108864,33554432,16777216,8388608,4194304,2097152,1048576,524288,262144,131072,65536,32768,16384,8192,4096,2048,1024,512,256,128,64,32,16,8,4,2,1};
inline int fphi(int x){
if (x==1) return 1;
if (binary_search(_phi,_phi+31,x,greater<int>())){
return _phi[lower_bound(_phi,_phi+31,x,greater<int>())-_phi+1];
}
exit(-2);
return phi(x);
}
struct Node{
int type;
char cdata;
ll idata;
Node(){
type=cdata=idata=0;
}
Node(char c){
if (c=='x') type=3;
else{
type=1;
cdata=c;
}
}
Node(ll i){
type=2;
idata=i;
}
operator char() const{
// assert(type==1);
return cdata;
}
operator ll() const{
// assert(type==2);
return idata;
}
};
struct Tree{
int ls,rs;
Node val;
};
int cnt;
string s;
vector<Node> op,dat;
Tree tr[1000000];
int newNode(Node x){
tr[++cnt]={0,0,x};
return cnt;
}
int check(Node x){
if (x.type==1){
char c=x.cdata;
if (c=='+' or c=='-') return 1;
else if (c=='*' or c=='/') return 2;
else if (c=='^') return 3;
else if (c=='(' or c==')') return 0;
}
return -1;
}
void print(const vector<Node> &v){
for (auto i:v){
if (i.type==3) cout<<"x ";
else if (i.type==1) cout<<i.cdata<<" ";
else cout<<i.idata<<" ";
}
}
void RPN(const string &s){
for (int i=0;i<s.size();){
if (isdigit(s[i])){
ll tmp=0;
for (;i<s.size() and isdigit(s[i]);i++) tmp=(tmp*10+(s[i]^48));
dat.push_back(tmp);
}else if (s[i]=='x'){
dat.push_back(s[i]);
i++;
}else if (s[i]=='('){
op.push_back(s[i]);
i++;
}else if (s[i]==')'){
char t=op.back();
while (t!='('){
op.pop_back();
dat.push_back(t);
t=op.back();
}
op.pop_back();
i++;
}else if (1<=check(s[i]) and check(s[i])<=3){
if (not op.empty()){
char t=op.back();
while (not op.empty() and check(s[i])<=check(t)){
if (check(s[i])==check(t) and s[i]=='^') break;
op.pop_back();
dat.push_back(t);
if (not op.empty()) t=op.back();
}
}
op.push_back(s[i]);
i++;
}
}
reverse(op.begin(),op.end());
op.insert(op.begin(),dat.begin(),dat.end());
}
vector<int> num;
int build(){
reverse(op.begin(),op.end());
while (not op.empty()){
Node t=op.back();
op.pop_back();
if (t.type!=1) num.push_back(newNode(t));
else{
int x=num.back();
num.pop_back();
int y=num.back();
num.pop_back();
num.push_back(newNode(t));
tr[num.back()].ls=y;
tr[num.back()].rs=x;
}
}
// assert(num.size()==1);
return num.back();
}
int dfs(int i){
if (tr[i].val.type==1){
char t=tr[i].val;
if (t=='+' or t=='-'){
int curr=newNode(t);
tr[curr].ls=dfs(tr[i].ls);
tr[curr].rs=dfs(tr[i].rs);
return curr;
}else if (t=='*'){ // (f(x)g(x))'=f(x)g'(x)+f'(x)g(x)
int curr=newNode('+');
tr[curr].ls=newNode('*');
tr[curr].rs=newNode('*');
tr[tr[curr].ls].ls=tr[i].ls;
tr[tr[curr].ls].rs=dfs(tr[i].rs);
tr[tr[curr].rs].ls=dfs(tr[i].ls);
tr[tr[curr].rs].rs=tr[i].rs;
return curr;
}else if (t=='^'){ // ((f(x))^n)'=n(f(x))^{n-1}f'(x)
int curr=newNode('*');
tr[curr].ls=newNode('*');
tr[tr[curr].ls].ls=tr[i].rs;
tr[tr[curr].ls].rs=newNode('^');
tr[tr[tr[curr].ls].rs].ls=tr[i].ls;
tr[tr[tr[curr].ls].rs].rs=newNode('~');
tr[tr[tr[tr[curr].ls].rs].rs].ls=tr[i].rs;
// tr[tr[tr[tr[curr].ls].rs].rs].rs=newNode(Node(1ll));
tr[curr].rs=dfs(tr[i].ls);
return curr;
}
}else if (tr[i].val.type==2){ // c
return newNode(Node(0ll));
}else if (tr[i].val.type==3){ // x
return newNode(Node(1ll));
}
assert(false);
__builtin_unreachable();
}
pair<ll,bool> eval(int i,ll x,int p){
assert(i!=0);
if (p==1) return {0,1};
if (tr[i].val.type==1){
char t=tr[i].val;
if (t=='+'){
auto [ansl,fl]=eval(tr[i].ls,x,p);
auto [ansr,fr]=eval(tr[i].rs,x,p);
return {(ansl+ansr)%p,fl or fr or ansl+ansr>=p};
}else if (t=='~'){
auto [ansl,fl]=eval(tr[i].ls,x,p);
return {(ansl-1+p)%p,fl};
}else if (t=='*'){
auto [ansl,fl]=eval(tr[i].ls,x,p);
auto [ansr,fr]=eval(tr[i].rs,x,p);
return {ansl*ansr%p,fl or fr or ansl*ansr>=p};
}else if (t=='^'){
int t=fphi(p);
auto [ansl,fl]=eval(tr[i].ls,x,p);
if (ansl==1 and not fl) return {1,0};
auto [ansr,fr]=eval(tr[i].rs,x,t);
if (ansr==0 and not fr) return {1,0};
if (ansl==0 and not fl) return {0,0};
if (ansr==1 and not fr) return {ansl,fl};
if (fr) ansr+=t;
return {qpow(ansl,ansr,p),fl or pow(ansl,ansr)>=p};
}
}else if (tr[i].val.type==2){ // c
return {tr[i].val.idata%p,tr[i].val.idata>=p};
}else if (tr[i].val.type==3){ // x
return {x%p,x>=p};
}
assert(false);
__builtin_unreachable();
}
void print(int i){
if (i){
print(tr[i].ls);
if (tr[i].val.type==1) cout<<tr[i].val.cdata<<" ";
else if (tr[i].val.type==2) cout<<tr[i].val.idata<<" ";
else cout<<"x ";
print(tr[i].rs);
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int T;
cin>>T;
while (T--){
cnt=0;
op.clear();
num.clear();
dat.clear();
ll x1,x2;
cin>>s>>x1>>x2;
RPN(s);
int rt=build();
rt=dfs(rt);
// print(rt);
// cout<<"*****\n";
cout<<eval(rt,x1,mod).first<<" "<<eval(rt,x2,mod).first<<"\n";
}
return 0;
}