Permutations 好题

 Permutations

Time Limit: 20000/10000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others)
SubmitStatus

Problem Description

给出两个正整数N、K,问存在多少个长度为N的排列,满足其峰顶数目为K。所谓排列就是有一个序列a[1] ...a[N],每个数均不相同,且都是1 

<= a[i] <= N,a[i]是峰顶的意思是 a[i] > a[i - 1] && a[i] > a[i + 1],对于边界,我们假设a[0] = -1000000000 和 a[N + 

1] = -1000000000

Input

多组数据,每组数据一行,N,K(1 <= N <= 10^18, 1 <= K <= 30)

Output

每组数据一行,你的答案 % 239

Sample Input

5 1
5 2
3 1
10 3

Sample Output

16
88
4
131

Hint

比如对于排列1 3 2 4 5,a[2] = 3和a[5] = 5都是峰顶,因此这个排列峰顶数目为2
 
 
  1 #include <iostream>
  2 #include <string.h>
  3 #include <algorithm>
  4 #include <math.h>
  5 #include <stdio.h>
  6 using namespace std;
  7 #define ll long long
  8 #define MAX 32
  9 #define mod 239
 10 struct matrix
 11 {
 12     int a[MAX][MAX];
 13 } origin,res,anss,ansa;
 14 matrix multiply(matrix x,matrix y)
 15 {
 16     matrix temp;
 17     memset(temp.a,0,sizeof(temp.a));
 18     int i,j,k;
 19     for(k=0; k<MAX; k++)
 20         for(i=0; i<MAX; i++)
 21             if(x.a[i][k])
 22                 for(j=0; j<MAX; j++)
 23                     temp.a[i][j]+=x.a[i][k]*y.a[k][j]%mod,temp.a[i][j]%mod;
 24     return temp;
 25 }
 26 void calc(ll x)
 27 {
 28     memset(res.a,0,sizeof(res.a));
 29     int i;
 30     for(i=0; i<MAX; i++)
 31         res.a[i][i]=1;
 32     while(x)
 33     {
 34         if(x&1)
 35             res=multiply(res,origin);
 36         origin=multiply(origin,origin);
 37         x>>=1;
 38     }
 39 }
 40 void init(int x)
 41 {
 42     memset(origin.a,0,sizeof(origin.a));
 43     int i,j;
 44     for(i=1; i<MAX; i++)
 45     {
 46         j=i-1;
 47         origin.a[i][i]=2*i;
 48         origin.a[i][j]=(x-2*j)%mod;
 49     }
 50 }
 51 int dp[241][241]= {0},ans;
 52 void init1()
 53 {
 54     int i,j;
 55     dp[1][1]=1;
 56     for(i=2; i<241; i++)
 57         for(j=1; j<i; j++)
 58             dp[i][j]=((dp[i-1][j]*2*j)%mod+(dp[i-1][j-1]*max(0,i-2*j+2))%mod)%mod;
 59 }
 60 int main()
 61 {
 62     init1();
 63     ll n,k,i,m,j,kk;
 64     while(~scanf("%lld%lld",&n,&k))
 65     {
 66         if(n<241)
 67         {
 68             printf("%d
",dp[n][k]);
 69             continue;
 70         }
 71         n-=239;
 72         ans=0;
 73         memset(anss.a,0,sizeof(anss.a));
 74         for(i=0; i<MAX; i++)anss.a[i][i]=1;
 75         for(kk=239; kk<478; kk++)
 76         {
 77             init(kk);
 78             anss=multiply(origin,anss);
 79             if((n%239)==(kk%239))
 80             {
 81                 for(i=0; i<MAX; i++)
 82                     for(j=0; j<MAX; j++)
 83                         ansa.a[i][j]=anss.a[i][j];
 84             }
 85         }
 86         n/=239;
 87         if(n)
 88         {
 89             for(i=0; i<MAX; i++)
 90                 for(j=0; j<MAX; j++)
 91                     origin.a[i][j]=anss.a[i][j];
 92             calc(n);
 93             ansa=multiply(ansa,res);
 94         }
 95         for(j=0; j<MAX; j++)
 96         {
 97             ans+=(dp[238][j]*ansa.a[k][j])%mod;
 98             ans%=mod;
 99         }
100         printf("%d
",ans);
101     }
102 }
View Code
原文地址:https://www.cnblogs.com/ERKE/p/3868668.html