NKOI 3124 珍珠吊坠

珍珠吊坠

Time Limit:10000MS  Memory Limit:65536K
Total Submit:25 Accepted:17
Case Time Limit:1000MS

Description

有k种珍珠,每种珍珠有N颗,问能组合出多少种含有k种珍珠且长度<=N的吊坠?(注意:吊坠为链状,非环状)

Input

一行,两个整数N和K

Output

一行,一个整数,表示所求方案总数,结果可能很大,mod 1234567891再输出

Sample Input

样例输入1:
2 1
样例输入2:
3 2

Sample Output

样例输出1:
2
样例输出2:
8

Hint

1 ≤ N ≤ 1,000,000,000
1 ≤ K ≤ 30
样例2说明:
设两种珍珠编号为1和2
1 2
2 1
1 1 2
1 2 1
2 1 1
2 2 1
2 1 2
1 2 2

Source

HDU2294



状态:
           dp[i][j]表示用j种珍珠构成长度恰好为i的吊坠,总的方案数
方程:
           dp[i][j] = (k-(j-1))*dp[i-1][j-1] + j*dp[i-1][j];
结果:
           ans[i]表示长度在i以内且满足条件的吊坠的总方案数
           ans[i]=dp[1][k]+dp[2][k]+...+dp[i][k]
           显然,问题的最终答案为ans[n]

但是考虑到n的范围,我们必须用矩阵乘法优化

根据前面的分析显然有:ans[i]=ans[i-1]+dp[i][k]
参考前面所讲的数列构造方法:
我们构造一个1*(k+1)的矩阵F{  dp[i][1], dp[i][2], dp[i][3], ... ,dp[i][k], ans[i-1]  }
我们希望再构造一个(k+1)*(k+1)的矩阵A,使得:F * A={ dp[i+1][1], dp[i+1][2], dp[i+1][3], ... , dp[i+1][k], ans[i] }

矩阵A的求法很好求,这里就不过多解释了

最终答案就是F*A^n;其中矩阵F的初始值:
{dp[1][1], dp[1][2], dp[1][3], ... ,dp[1][k], ans[0]}
={    k    ,     0      ,      0     , ... ,   0      ,    0      }

#include<iostream>
#include<cstdio>
#include<cstring>
#define LL long long
using namespace std;
const int mod=1234567891;
typedef LL arr[35][35];
arr z,A,ans;
LL k,n;
void cheng(arr y,arr x){
	memset(z,0,sizeof(z));
	LL i,j,q;
    for(i=1;i<=k+1;i++)
       for(j=1;j<=k+1;j++)
          for(q=1;q<=k+1;q++)
             z[i][j]=(z[i][j]+y[i][q]*x[q][j])%mod;
    memcpy(y,z,sizeof(z));
}
void mb(LL b){
	LL i;
	for(i=1;i<=k+1;i++)ans[i][i]=1;
    while(b){
    if(b&1)cheng(ans,A);
        b>>=1;
        cheng(A,A);
    }
}
int main(){
	scanf("%I64d%I64d",&n,&k);
	LL i,j;
	A[k+1][k+1]=A[k][k+1]=1,A[k][k]=k;
	for(i=1;i<k;i++)
	    A[i][i]=i,A[i][i+1]=k-i;
	mb(n);
	cout<<(k*ans[1][k+1])%mod;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值