时间限制 1000 ms 内存限制 256 MB
现有一个多项式Pn(x)Pn(x),其满足
其中为n阶导数。小Q认为这个式子太复杂了,希望你能帮他化简。
输入数据
一个正整数 n(2≤n≤30)n(2≤n≤30) 表示多项式次数。
输出数据
一行,共n+1n+1个数,表示多项式按幂次从高到低的系数。
样例输入
3
样例输出
5/2 0 -3/2 0
说明
化简后的多项式为
题解:
首先对进行化简,
我们先对二项式进行展开,可以得到:
其中第i项的n阶导数为:
在求解的过程中,因为n可能为30,在求解的过程中可能爆int,所以我们对n!进行质因数分解;
我们可以看到二项式中x的系数是2i,所以在求的过程中,有些项直接就是零,
#include <iostream>
#include<string.h>
#include <algorithm>
using namespace std;
int cnt=0;
int prime[17] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59 };
int bucket[17];//储存质因数的个数
long long ksm(int a, int b) { //快速幂
long long ans = 1;
while (b > 0) {
if (b % 2 == 1) {
ans = a * ans;
}
a = a * a;
b /= 2;
}
return ans;
}
void factprime(int n, int fenzi) {//分子做加法,分母做减法
//n!的质因数分解
for (int i = 0; i < 17; i++) {
int temp = n;
while (temp) {
bucket[i] += fenzi * temp / prime[i];
temp /= prime[i];
}
}
}
void run(int k,int n) {
int i = (k + n) / 2; //计算阶乘中的i
memset(bucket, 0, sizeof bucket);
factprime(2 * i, 1);
factprime(n-i, -1);
factprime(i, -1);
factprime(2 * i - n, -1);
bucket[0] -= n; //除以2^ n
long long p=1, q=1;//计算分子、分母
for (int i = 0; i < 17; i++) {
if (bucket[i] < 0) {
p *= ksm(prime[i], -bucket[i]);
}
else
q *= ksm(prime[i], bucket[i]);
}
if (cnt)
printf(" "); //打印空格
if((n-i)%2==1)
printf("-"); //计算-1项的系数
printf("%lld/%lld", q, p);
}
int main() {
int n;
cin >> n;
for (int i = n; i >= 0; i--) { //判断有些项是0
if (n % 2 == 0) {
if (i % 2 == 0) {
run(i,n);
}
else {
if (cnt)
printf(" ");
printf("0");
}
}
else {
if (i % 2 == 1) {
run(i,n);
}
else {
if (cnt)
printf(" ");
printf("0");
}
}
cnt++;
}
}