【HDU 3483】 A Very Simple Problem (二项式展开+矩阵加速)

A Very Simple Problem

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1022    Accepted Submission(s): 500


Problem Description
This is a very simple problem. Given three integers N, x, and M, your task is to calculate out the following value:

Input
There are several test cases. For each case, there is a line with three integers N, x, and M, where 1 ≤ N, M ≤ 2*109, and 1 ≤ x ≤ 50.
The input ends up with three negative numbers, which should not be processed as a case.
Output
For each test case, print a line with an integer indicating the result.
Sample Input
100 1 10000
3 4 1000
-1 -1 -1
Sample Output
5050
444
Source

【分析】

  感觉我的思想离正解还是太远太远,根本不会这样想。

  首先我们发现x很小,k很大,k达到了10^9,for一遍都不行,这样我们就想到ans可能存在递推式,然后可以用矩阵加速。

  

转自:http://972169909-qq-com.iteye.com/blog/1863402

  太厉害了,我自己都好难再推一次~~

代码如下:

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<queue>
 7 #include<cmath>
 8 using namespace std;
 9 #define Maxn 60
10 #define LL long long
11 
12 LL c[Maxn][Maxn];
13 LL n,x,M;
14 
15 struct node
16 {
17     LL a[Maxn][Maxn];
18 }t[5];
19 
20 void init()
21 {
22     memset(c,0,sizeof(c));
23     for(LL i=0;i<=50;i++) c[i][0]=1;
24     for(LL i=1;i<=50;i++)
25      for(LL j=1;j<=50;j++)
26          c[i][j]=(c[i-1][j-1]+c[i-1][j])%M;
27 }
28 
29 void get_un()
30 {
31     memset(t[1].a,0,sizeof(t[1].a));
32     for(LL i=0;i<=x+1;i++) t[1].a[i][i]=1%M;
33 }
34 
35 void mul(LL now,LL y,LL z)
36 {
37     for(int i=0;i<=x+1;i++)
38      for(int j=0;j<=x+1;j++)
39      {
40          t[2].a[i][j]=0;
41          for(LL k=0;k<=x+1;k++)
42           t[2].a[i][j]=(t[2].a[i][j]+t[y].a[i][k]*t[z].a[k][j])%M;
43      }
44     t[now]=t[2];
45 }
46 
47 void qpow(LL b)
48 {
49     get_un();
50     while(b)
51     {
52         if(b&1) mul(1,0,1);
53         mul(0,0,0);
54         b>>=1;
55     }
56 }
57 
58 int main()
59 {
60     while(1)
61     {
62         scanf("%lld%lld%lld",&n,&x,&M);
63         if(n==-1&&x==-1&&M==-1) break;
64         init();
65         for(LL i=0;i<=x;i++)
66         {
67             for(LL j=0;j<=i;j++) t[0].a[i][j]=(x*c[i][j])%M;
68             for(LL j=i+1;j<=x+1;j++) t[0].a[i][j]=0;
69         }
70         for(LL i=0;i<x;i++) t[0].a[x+1][i]=0;
71         t[0].a[x+1][x]=t[0].a[x+1][x+1]=1%M;
72         // get_un();
73         qpow(n+1);
74         printf("%lld
",t[1].a[x+1][0]);
75     }
76     return 0;
77 }
[HDU 3483]

2016-09-25 22:07:05

原文地址:https://www.cnblogs.com/Konjakmoyu/p/5907143.html