zoj 3237

题意:一个方程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 }
原文地址:https://www.cnblogs.com/Rlemon/p/3052363.html