zoukankan      html  css  js  c++  java
  • Codeforces 551D GukiZ and Binary Operations(矩阵快速幂)

    Problem D. GukiZ and Binary Operations

    Solution 

          一位一位考虑,就是求一个二进制序列有连续的1的种类数和没有连续的1的种类数。

         没有连续的1的二进制序列的数目满足f[i]=f[i-1]+f[i-2],恰好是斐波那契数列。

         数据范围在10^18,用矩阵加速计算,有连续的1的数目就用2^n-f[n+1]

         最后枚举k的每一位,是1乘上2^n-f[n+1],是0乘上f[n+1]

         注意以上需要满足 2^l>k。并且这里l的最大值为64,需要特判。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef unsigned long long ll;
    const int N = 2;
    ll n, k, l, m;
    
    struct Mat {
        ll mat[N + 1][N + 1];
    } A, B;
    
    Mat operator * ( Mat a, Mat b )
    {
        Mat c;
        memset ( c.mat, 0, sizeof c.mat );
        for ( int k = 0; k <  N; k++ )
            for ( int i = 0; i <  N; i++ )
                for ( int j = 0; j <  N; j++ )
                    ( c.mat[i][j] += ( a.mat[i][k] * b.mat[k][j] ) % m ) %= m;
        return c;
    }
    
    Mat operator ^ ( Mat a, ll pow )
    {
        Mat c;
        for ( int i = 0; i <  N; i++ )
            for ( int j = 0; j <  N; j++ )
                c.mat[i][j] = ( i == j );
        while ( pow ) {
            if ( pow & 1 )     c = c * a;
            a = a * a;
            pow >>= 1;
        }
        return c;
    }
    
    ll quickp( ll x )
    {
        ll s = 1, c = 2;
        while( x ) {
            if( x & 1 ) s = ( s * c ) % m;
            c = ( c * c ) % m;
            x >>= 1;
        }
        return s;
    }
    int main()
    {
        ios::sync_with_stdio( 0 );
        Mat p, a;
        p.mat[0][0] = 0, p.mat[0][1] = 1;
        p.mat[1][0] = 1, p.mat[1][1] = 1;
        a.mat[0][0] = 1, a.mat[0][1] = 2;
        a.mat[1][0] = 0, a.mat[1][1] = 0;
        cin >> n >> k >> l >> m;
    
        ll ans = 0;
        if(  l == 64 || ( 1uLL << l ) > k  ) {
            ans++;
            p = p ^ n;
            a = a * p;
            ll t1 = a.mat[0][0], t2 = ( m + quickp( n ) - t1 ) % m;
            for( int i = 0; i < l; ++i ) {
                if( k & ( 1uLL << i ) ) ans = ( ans * t2 ) % m;
                else ans = ( ans * t1 ) % m;
            }
        }
    
        cout << ans%m << endl;
    
    }
    View Code
  • 相关阅读:
    Netty实现Http客户端
    Netty实现Http服务端
    Netty实现Tcp客户端
    Netty实现Tcp服务端
    MySQL进阶系列:一文详解explain
    spring boot 获取运行时的yml里的active配置
    eureka 注册中心添加认证
    zuul 负载
    jenkins spring cloud
    秒杀系统如何设计?
  • 原文地址:https://www.cnblogs.com/keam37/p/4578568.html
Copyright © 2011-2022 走看看