题意:一个方程f(t)=a[n]*t^n+a[n-1]*t^(n-1)+...+a[1]*t;
它有n-1个极值点,求每个系数ai小数点后第一个非零值,如果是整数则输出0;
f(t)求导后,是n-1次的函数,f(t)==0最多有n-1的解,因为告诉你有n-1个极值点,所以
f(t)=(x+t1)*(x+t2)*(x+t3)...(x+tn-1);系数可以直接搞用n^2的方法;
dp[i][j]表示前i项(x+ti)相乘x^j的系数;
这题感觉比较好的想法是,因为ti<10000,所以最终系数可能爆LL;但因为最后要求的系数都是
一个整数除以i(i<=n),因为n<32,可以先求出1~n的最小公倍数;然后系数对这个数去摸,这样
就不会影响最终除以i的解;
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<cmath> 6 #include<vector> 7 #include<cstring> 8 using namespace std; 9 typedef long long LL; 10 const int N=40; 11 int t[N],n; 12 LL mod; 13 LL lcm(LL a,LL b){ 14 return a/__gcd(a,b)*b; 15 } 16 void init(){ 17 mod=1; 18 for (int i=2;i<=n;i++) mod=lcm(mod,i); 19 } 20 LL dp[N][N]; 21 int cal(LL a,int x){ 22 if (a<0) a+=mod; 23 if (a%x==0) return 0; 24 a=a%x; 25 while (1){ 26 if (a<x) a*=10; 27 else { 28 return a/x; 29 } 30 } 31 } 32 void work(){ 33 dp[0][0]=1; 34 // cout<<"*** "<<endl; 35 for (int i=1;i<n;i++){ 36 dp[i][0]=(-dp[i-1][0]*t[i])%mod; 37 for (int j=1;j<=i;j++){ 38 dp[i][j]=(dp[i-1][j-1]-dp[i-1][j]*t[i])%mod; 39 } 40 // for (int j=0;j<=i;j++) cout<<dp[i][j]<<" "; 41 // cout<<endl; 42 } 43 // cout<<"**** "<<endl; 44 45 printf("0"); 46 for (int i=1;i<n;i++){ 47 printf(" %d",cal(dp[n-1][i],i+1)); 48 } 49 printf("\n"); 50 51 } 52 int main(){ 53 int T,cas=0;scanf("%d",&T); 54 while (T--){ 55 scanf("%d",&n); 56 for (int i=1;i<n;i++) { 57 scanf("%d",&t[i]); 58 t[i]=-t[i]; 59 } 60 init(); 61 work(); 62 } 63 return 0; 64 }