LuoguP4893 GodFly的求导工具 题解

Description

题目链接

给定一个 $n$ 次整系数函数 $f(x)$,问 $f(x)$ 的 $k$ 阶导在 $x_i$ 处的导数。

$1\leq n \leq 100,k\leq n,m\leq 10,a_i\leq 10^5,x_i\leq 10^5$

Solution

很好奇这题是怎么评紫的(?

咳咳,对于这道题,你先要有亿简单高等数学知识。

  • $f(x)=x^p$ 的 $k$ 阶导函数为 $f^{(k)}(x)=\prod_{i=1}^k(p-i+1)x^{p-k}$
  • $f(x)=g(x)+h(x)$ 的 $k$ 阶导函数为 $f^{(k)}(x)=g^{(k)}(x)+h^{(k)}(x)$

证明略(

假设你已经熟知了以上结论,那么就可以愉快的把这道题切掉了。

直接暴力拆出每一项的系数,暴力进行求导,找到其 $k$ 阶导函数,对于每个询问,直接暴力带入即可。

因为 $a_i\leq 10^5,x_i \leq 10^5$ 可能会导致答案爆 $int$,所以你还要耐心地写一个高精套一个高精模板。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define W while
#define I inline
#define RI register int
#define LL long long
#define Cn const
#define gc getchar
#define DD isdigit(c=gc())
#define pc(c) putchar((c))
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
using namespace std;
namespace Debug{
Tp I void _debug(Cn char* f,Ty t){cerr<<f<<'='<<t<<endl;}
Ts I void _debug(Cn char* f,Ty x,Ar... y){W(*f!=',') cerr<<*f++;cerr<<'='<<x<<",";_debug(f+1,y...);}
Tp ostream& operator<<(ostream& os,Cn vector<Ty>& V){os<<"[";for(Cn auto& vv:V) os<<vv<<",";os<<"]";return os;}
#define gdb(...) _debug(#__VA_ARGS__,__VA_ARGS__)
}using namespace Debug;
namespace FastIO{
Tp I void read(Ty& x){char c;int f=1;x=0;W(!DD) f=c^'-'?1:-1;W(x=(x<<3)+(x<<1)+(c&15),DD);x*=f;}
Ts I void read(Ty& x,Ar&... y){read(x),read(y...);}
Tp I void write(Ty x){x<0&&(pc('-'),x=-x,0),x<10?(pc(x+'0'),0):(write(x/10),pc(x%10+'0'),0);}
Tp I void writeln(Cn Ty& x){write(x),pc('\n');}
}using namespace FastIO;
Cn int N=110;
class Int{//Manchery的高精模板
#define BASE 1000000000
public:
typedef long long value;
void New(size_t l){
if (a!=NULL)delete[] a;a=new value[l];
len=1;a[0]=0;sign=1;
}
Int():a(NULL),base(BASE){New(1);}
Int(value x):a(NULL),base(BASE){New(1);*this=x;}
Int(value x,value _base):a(NULL),base(_base){New(1);*this=x;}
Int(const Int &B):a(NULL),base(BASE){New(1);*this=B;}
~Int(){delete[] a;}
Int& operator =(value x){
size_t l=1;for (value x1=max(x,-x);x1>=base;++l,x1/=base);New(l);
if (x<0)x=-x,sign=0;else sign=1;
len=0;while (x)a[len++]=x%base,x/=base;
if (!len)a[len++]=0;
return *this;
}
Int& operator =(const Int &A){
New(A.len);len=A.len;memcpy(a,A.a,sizeof(value)*len);
base=A.base;sign=A.sign;return *this;
}
friend Int operator -(Int A){A.sign=1-A.sign;return A;}
bool operator !(){if (len==1&&a[0]==0)return 1;else return 0;}
friend Int operator +(Int A,Int B){
if (A.sign!=B.sign){B.sign=1-B.sign;return A-B;}
if (A.base!=B.base)
if (A.base>B.base)B.set_base(A.base);
else A.set_base(B.base);
Int res;res.set_base(A.base); int len=A.len>B.len?A.len:B.len;
res.New(len+1);res.sign=A.sign;
memset(res.a,0,(len+1)*sizeof(value));
for (int i=0;i<len;++i){
if (i<A.len)res.a[i]+=A.a[i];
if (i<B.len)res.a[i]+=B.a[i];
}
for (int i=0;i<len;++i)
if (res.a[i]>=res.base)++res.a[i+1],res.a[i]-=res.base;
if (res.a[len])res.len=len+1;else res.len=len;
if (!res)res.sign=1;return res;
}
friend Int operator -(Int A,Int B){
if (A.sign!=B.sign){B.sign=1-B.sign;return A+B;}
if (A.base!=B.base)
if (A.base>B.base)B.set_base(A.base);
else A.set_base(B.base);
if (small(A,B))swap(A,B),A.sign=1-A.sign;
Int res;res.set_base(A.base); int len=A.len>B.len?A.len:B.len;
res.New(len);res.sign=A.sign;
memset(res.a,0,len*sizeof(value));
for (int i=0;i<len;++i){
if (i>=B.len)res.a[i]+=A.a[i];
else res.a[i]+=A.a[i]-B.a[i];
if (res.a[i]<0)res.a[i]+=res.base,--res.a[i+1];
}
while (len>1&&!res.a[len-1])--len;res.len=len;
if (!res)res.sign=1;return res;
}
friend Int operator *(Int A,Int B){
if (A.base!=B.base)
if (A.base>B.base)B.set_base(A.base);
else A.set_base(B.base);
Int res;res.set_base(A.base); int len=A.len+B.len;
res.New(len);res.sign=(A.sign==B.sign);
memset(res.a,0,len*sizeof(value));
for (int i=0;i<A.len;++i)
for (int j=0;j<B.len;++j){
res.a[i+j]+=A.a[i]*B.a[j];
res.a[i+j+1]+=res.a[i+j]/res.base;
res.a[i+j]%=res.base;
}
/*
for (int i=0;i<A.len;++i)
for (int j=0;j<B.len;++j)res.a[i+j]+=A.a[i]*B.a[j];
for (int i=0;i<len-1;++i)res.a[i+1]+=res.a[i]/res.base,res.a[i]%=res.base;
*/
while (len>1&&!res.a[len-1])--len;res.len=len;
return res;
}
friend pair<Int,Int> divide(Int A,Int B){
if (!B){puts("error:div zero!");for (;;);}
if (A.base!=B.base)
if (A.base>B.base)B.set_base(A.base);
else A.set_base(B.base);
if (small(A,B))return make_pair(Int(0),A);
Int C,D;C.set_base(A.base);D.set_base(A.base);C.New(A.len);C.len=A.len;
bool Csign=(A.sign==B.sign),Dsign=A.sign;A.sign=B.sign=1;
for (int i=A.len-1;i>=0;--i){
C.a[i]=0;D=D*D.base;D.a[0]=A.a[i];
int l=0,r=A.base-1,mid;
while (l<r){
mid=(l+r+1)>>1;
if (small(B*mid,D+1))l=mid;
else r=mid-1;
}
C.a[i]=l;D=D-B*l;
}
C.sign=Csign;D.sign=Dsign;if (!D)D.sign=1;
while (C.len>1&&!C.a[C.len-1])--C.len;
return make_pair(C,D);
}
Int operator /(value x){
if (!x){puts("error:div zero!");for (;;);}
value d=0;Int res;res.set_base(base);res.New(len);res.len=len;
if (x<0)x=-x,res.sign=(sign==0);
else res.sign=(sign==1);
for (int i=len-1;i>=0;--i)
d=d*base+a[i],res.a[i]=d/x,d%=x;
while (res.len>1&&!res.a[res.len-1])--res.len;
return res;
}
Int operator %(value x){
value d=0;if (x<0)x=-x;
for (int i=len-1;i>=0;--i)d=(d*base+a[i])%x;
return d;
}
friend Int abs(Int A){A.sign=1;return A;}
friend bool small(Int A,Int B){
if (A.base!=B.base)
if (A.base>B.base)B.set_base(A.base);
else A.set_base(B.base);
if (A.len!=B.len)return A.len<B.len;
for (int i=A.len-1;i>=0;--i)
if (A.a[i]!=B.a[i])return A.a[i]<B.a[i];
return 0;
}
friend bool operator <(Int A,Int B){
if (A.sign!=B.sign)return A.sign<B.sign;
return A.sign==1?small(A,B):small(B,A);
}
friend bool operator ==(Int A,Int B){
if (A.base!=B.base)
if (A.base>B.base)B.set_base(A.base);
else A.set_base(B.base);
if (A.sign!=B.signA.len!=B.len)return 0;
for (int i=0;i<A.len;++i)if (A.a[i]!=B.a[i])return 0;
return 1;
}
friend bool operator !=(Int A,Int B){return !(A==B);}
friend bool operator >(Int A,Int B){return !(A<BA==B);}
friend bool operator <=(Int A,Int B){return A<BA==B;}
friend bool operator >=(Int A,Int B){return A>BA==B;}
Int operator /(Int B){return divide(*this,B).first;}
Int operator %(Int B){return divide(*this,B).second;}
Int& operator +=(Int B){*this=*this+B;return *this;}
Int& operator -=(Int B){*this=*this-B;return *this;}
Int& operator *=(Int B){*this=*this*B;return *this;}
Int& operator /=(Int B){*this=*this/B;return *this;}
Int& operator %=(Int B){*this=*this%B;return *this;}
Int& operator ++(){*this=*this+1;return *this;}
Int& operator --(){*this=*this-1;return *this;}
Int operator ++(int){Int res(*this);*this=*this+1;return res;}
Int operator --(int){Int res(*this);*this=*this-1;return res;}
Int operator +(value x){return *this+Int(x,this->base);}
Int operator -(value x){return *this-Int(x,this->base);}
Int operator *(value x){return *this*Int(x,this->base);}
//Int operator /(value x){Int T;T=x;return *this/T;}
//Int operator %(value x){Int T;T=x;return *this%T;}
Int& operator *=(value x){*this=*this*x;return *this;}
Int& operator +=(value x){*this=*this+x;return *this;}
Int& operator -=(value x){*this=*this-x;return *this;}
Int& operator /=(value x){*this=*this/x;return *this;}
Int& operator %=(value x){*this=*this%x;return *this;}
bool operator ==(value x){return *this==Int(x,this->base);}
bool operator !=(value x){return *this!=Int(x,this->base);}
bool operator <=(value x){return *this<=Int(x,this->base);}
bool operator >=(value x){return *this>=Int(x,this->base);}
bool operator <(value x){return *this<Int(x,this->base);}
bool operator >(value x){return *this>Int(x,this->base);}
friend Int gcd(Int x,Int y){
Int t;int cnt=0;
while (1){
if (x<y)t=x,x=y,y=t;
if (y==0){
while (cnt--)x*=2;
return x;
}
if (x%2==0&&y%2==0)x/=2,y/=2,++cnt;
else if (x%2==0)x/=2;
else if (y%2==0)y/=2;
else {t=x;x=y;y=t-y;}
}
}
void to_arr(char *c){
char *c1=c;
for (int i=0;i<len-1;++i)
for (value x=a[i],b=base/10;b>=1;b/=10)*c1++='0'+x%10,x/=10;
for (value x=a[len-1];x>0;x/=10)*c1++='0'+x%10;
if (len==1&&a[len]==0)*c1++='0';
if (sign==0)*c1++='-';*c1=0;reverse(c,c1);
}
void from_arr(char *c){
size_t base_l=get_basel(),b=1;int cl=strlen(c);value x=0;
New((cl+base_l-1)/base_l);len=0;
if (*c=='-')sign=0,++c,--cl;else sign=1;
while (--cl>=0){
x+=(c[cl]-'0')*b;b*=10;if (b==base)a[len++]=x,x=0,b=1;
}
if (!lenx)a[len++]=x;
while (len>1&&!a[len-1])--len;
}
void set_base(int _base){
if (base==_base)return;
char *c=new char[len*get_basel()+1];
to_arr(c);base=_base;from_arr(c);
delete[] c;
}
void set_basel(int _l){
size_t _base=1;while (_l--)_base*=10;set_base(_base);
}
void read(){
vector<char> s;char ch;
scanf(" %c",&ch);if (ch=='-')s.push_back('-'),ch=getchar();
for (;ch>='0'&&ch<='9';ch=getchar())s.push_back(ch);
char *c=new char[s.size()+1];
for (int i=0;i<s.size();++i)c[i]=s[i];c[s.size()]=0;
from_arr(c);delete[] c;
if (!*this)this->sign=1;
}
void print(){
if (!sign)putchar('-');
printf("%d",int(a[len-1]));
for (int i=len-2;i>=0;--i){
for (int j=base/10;j>=10;j/=10)
if (a[i]<j)putchar('0');
else break;
printf("%d",(int)a[i]);
}
}
void println(){print();putchar('\n');}
private:
value *a,base;int len;bool sign; //0="-"
size_t get_basel()const{
size_t res=0;for (int b=base/10;b>=1;b/=10,++res);
return res;
}
#undef BASE
};
Int num[N],Ans[N],top=1,ans;
int n,m,k,len;
string str;
I Int fpow(int a,int b){Int A=a,s=1;W(b!=0){if(b%2==1) s*=A;A*=A;b=b/2;}return s;}//高精快速幂
int main(){
RI i,j,s;for(read(n,k),cin>>str,len=str.length(),i=5;i<len;)
if(isdigit(str[i])){j=i+1;s=str[i]-'0';W(j<len&&isdigit(str[j])) s=s*10+str[j]-'0',j++;top=s,i=j;}//处理系数
else if(str[i]=='x'){j=i+1;s=0;W(j<len&&str[j]!='^') ++j;j++;W(j<len&&isdigit(str[j])) s=s*10+str[j]-'0',++j;num[s]+=top;top=1;i=j;}//处理次数
else i++;
for(i=0;i<=n;i++)
if(i-k>=0) for(Ans[i-k]=num[i],j=1;j<=k;j++) Ans[i-k]*=i-j+1;//直接求导套公式
for(read(m);m--;){for(read(s),ans=j=0;j<=n;j++) ans=ans+Ans[j]*fpow(s,j);ans.println();}//对于每个询问直接暴力计算
return 0;
}