HDU4651 Partition 【多项式求逆】

题目分析:

这题的做法是一个叫做五边形数定理的东西,我不会。

我们不难发现第$n$项的答案其实是:

$$\prod_{i=1}^{\infty}\frac{1}{1-x^i}$$

我们要对底下的东西求逆,可以尝试打表找一下这个的规律,就会发现底下那个函数,系数要么是$1$,要么是$-1$,要么是$0$。

而且这个函数是稀疏的,前$100000$项只有$515$项非$0$。可以打出表后暴力求逆。

所以这道题我们有了一个$O(515*n)$的做法。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn = 110000;
 5 const int mod = 1000000007;
 6 
 7 int num = 259;
 8 int a[1010] ={0,5,7,22,26,51,57,92,100,145,155,210,222,287,301,376,392,477,495,590,610,715,737,852,876,1001,1027,1162,1190,1335,1365,1520,1552,1717,1751,1926,1962,2147,2185,2380,2420,2625,2667,2882,2926,3151,3197,3432,3480,3725,3775,4030,4082,4347,4401,4676,4732,5017,5075,5370,5430,5735,5797,6112,6176,6501,6567,6902,6970,7315,7385,7740,7812,8177,8251,8626,8702,9087,9165,9560,9640,10045,10127,10542,10626,11051,11137,11572,11660,12105,12195,12650,12742,13207,13301,13776,13872,14357,14455,14950,15050,15555,15657,16172,16276,16801,16907,17442,17550,18095,18205,18760,18872,19437,19551,20126,20242,20827,20945,21540,21660,22265,22387,23002,23126,23751,23877,24512,24640,25285,25415,26070,26202,26867,27001,27676,27812,28497,28635,29330,29470,30175,30317,31032,31176,31901,32047,32782,32930,33675,33825,34580,34732,35497,35651,36426,36582,37367,37525,38320,38480,39285,39447,40262,40426,41251,41417,42252,42420,43265,43435,44290,44462,45327,45501,46376,46552,47437,47615,48510,48690,49595,49777,50692,50876,51801,51987,52922,53110,54055,54245,55200,55392,56357,56551,57526,57722,58707,58905,59900,60100,61105,61307,62322,62526,63551,63757,64792,65000,66045,66255,67310,67522,68587,68801,69876,70092,71177,71395,72490,72710,73815,74037,75152,75376,76501,76727,77862,78090,79235,79465,80620,80852,82017,82251,83426,83662,84847,85085,86280,86520,87725,87967,89182,89426,90651,90897,92132,92380,93625,93875,95130,95382,96647,96901,98176,98432,99717,99975};
 9 int b[1010] = {1,2,12,15,35,40,70,77,117,126,176,187,247,260,330,345,425,442,532,551,651,672,782,805,925,950,1080,1107,1247,1276,1426,1457,1617,1650,1820,1855,2035,2072,2262,2301,2501,2542,2752,2795,3015,3060,3290,3337,3577,3626,3876,3927,4187,4240,4510,4565,4845,4902,5192,5251,5551,5612,5922,5985,6305,6370,6700,6767,7107,7176,7526,7597,7957,8030,8400,8475,8855,8932,9322,9401,9801,9882,10292,10375,10795,10880,11310,11397,11837,11926,12376,12467,12927,13020,13490,13585,14065,14162,14652,14751,15251,15352,15862,15965,16485,16590,17120,17227,17767,17876,18426,18537,19097,19210,19780,19895,20475,20592,21182,21301,21901,22022,22632,22755,23375,23500,24130,24257,24897,25026,25676,25807,26467,26600,27270,27405,28085,28222,28912,29051,29751,29892,30602,30745,31465,31610,32340,32487,33227,33376,34126,34277,35037,35190,35960,36115,36895,37052,37842,38001,38801,38962,39772,39935,40755,40920,41750,41917,42757,42926,43776,43947,44807,44980,45850,46025,46905,47082,47972,48151,49051,49232,50142,50325,51245,51430,52360,52547,53487,53676,54626,54817,55777,55970,56940,57135,58115,58312,59302,59501,60501,60702,61712,61915,62935,63140,64170,64377,65417,65626,66676,66887,67947,68160,69230,69445,70525,70742,71832,72051,73151,73372,74482,74705,75825,76050,77180,77407,78547,78776,79926,80157,81317,81550,82720,82955,84135,84372,85562,85801,87001,87242,88452,88695,89915,90160,91390,91637,92877,93126,94376,94627,95887,96140,97410,97665,98945,99202,100492};
10 
11 int n,iv[maxn],res[maxn];
12 
13 void work(){
14     iv[0] = 1;for(int i=0;i<num;i++) res[a[i]]=1,res[b[i]] = mod-1;
15     for(int i=1;i<=n;i++){
16         if(res[i] != 0){
17             iv[i] = mod-res[i];
18             for(int j=0;j<num;j++){
19                 if(a[j] + i > n) break;
20                 res[a[j]+i] += iv[i];
21                 if(res[a[j]+i] >= mod) res[a[j]+i]-=mod;
22             }
23             for(int j=0;j<num;j++){
24                 if(b[j] + i > n) break;
25                 res[b[j]+i] -= iv[i];
26                 if(res[b[j]+i] < 0) res[b[j]+i] += mod;
27             }
28         }
29     }
30 }
31 
32 int main(){
33     n = 100005;
34     work();
35     int T; scanf("%d",&T);
36     while(T--){
37         scanf("%d",&n);
38         printf("%d\n",iv[n]);
39     }
40     return 0;
41 }

猜你喜欢

转载自www.cnblogs.com/Menhera/p/10272039.html