HDU 4914 Linear recursive sequence(矩阵乘法递推的优化)

题解见X姐的论文 矩阵乘法递推的优化,只是mark一下。。


#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
        
        
using namespace std;
typedef __int64 ll;
const double pi = acos(-1.0);
const int N = 10000+5;
const double eps = 1e-6;
const int MOD = 119;

struct Complex {
        double x,y;
        Complex(double _x=0,double _y=0)
                        :x(_x),y(_y) {}
        Complex operator + (const Complex& tt)const { return Complex(x+tt.x,y+tt.y); }
        Complex operator - (const Complex& tt)const { return Complex(x-tt.x,y-tt.y); }
        Complex operator * (const Complex& tt)const { return Complex(x*tt.x-y*tt.y,x*tt.y+y*tt.x); }
};
void FFT(Complex *a, int n, int rev) {
        // n是大于等于相乘的两个数组长度的2的幂次
        // 从0开始表示长度,对a进行操作
        // rev==1进行DFT,==-1进行IDFT
        for (int i = 1,j = 0; i < n; ++ i) {
                for (int k = n>>1; k > (j^=k); k >>= 1);
                if (i
        
        
          = MOD) x -= MOD; } void mul(int *tmp1, int *tmp2, int maxn) { //for(int i = 0;i < q; i++) printf("%d ", tmp1[i]); puts(""); //for(int i = 0;i < q; i++) printf("%d ", tmp2[i]); puts(""); for(int i = 0;i < maxn; i++) { a1[i].x = a1[i].y = a2[i].x = a2[i].y = 0; if(i < q) { a1[i].x = 1.0*tmp1[i]; a2[i].x = 1.0*tmp2[i]; } } FFT(a1, maxn, 1); FFT(a2, maxn, 1); for(int i = 0;i < maxn; i++) a1[i] = a1[i]*a2[i]; FFT(a1, maxn, -1); for(int i = 0;i < maxn; i++) Fuck[i] = (ll)(a1[i].x+eps)%MOD; for(int i = q*2-2;i >= q; i--) { if(Fuck[i]) { Fuck[i-q] = (Fuck[i-q] + Fuck[i]*b)%MOD; Fuck[i-p] = (Fuck[i-p] + Fuck[i]*a)%MOD; } } //printf("q = %d\n", q); for(int i = 0;i < q; i++) { tmp1[i] = (int)Fuck[i]; } } int ans[N], tmp[N], f[N]; int solve() { a %= MOD; b %= MOD; f[0] = 1; for(int i = 1;i < q; i++) { if(i-p < 0) f[i] = a+b; else if(i < q) f[i] = (a*f[i-p]+b)%MOD; } if(n < q) { return f[n]; } int maxn = 1; while(maxn <= (q-1)*2) maxn <<= 1; for(int i = 0;i < q; i++) ans[i] = tmp[i] = 0; ans[0] = 1; tmp[1] = 1; int fuck = n; while(n) { if(n&1) { mul(ans, tmp, maxn); } mul(tmp, tmp, maxn); n >>= 1; } int ret = 0; for(int i = 0;i < q; i++) { Add(ret, ans[i]*f[i]%MOD); } n = fuck; return ret; } int main() { while(input()) { printf("%d\n", solve()); } return 0; } 
        
       
       
      
      
     
     
    
    

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值