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 }

 

 

你可能感兴趣的:(ZOJ)