1. 程式人生 > >ACM-ICPC 2018 焦作賽區網路預賽 G 隔板+費馬小定理 L矩陣快速冪

ACM-ICPC 2018 焦作賽區網路預賽 G 隔板+費馬小定理 L矩陣快速冪

G

思路:隔板法知道結果是 2 ^ ( n - 1 ),n過大。 費馬小定理為 a^(p-1) ≡ 1 mod p ; a, p 互質,p為質數。 所以2^(p-1)% p 為1,2^k*(p-1) % p 也為1,所以找出n = k*(p-1) + m 。只需要求2 ^ m 即可。

Code:

#include <bits/stdc++.h>
#define LL long long 
#define mod 1000000007
using namespace std;
char s[1000006];
LL quick( LL a , LL k ){
    LL ans = 1LL ;
    while
( k ){ if( k & 1 ){ ans = ( ans * a ) % mod ; k -- ; } k >>= 1 ; a = ( a * a ) % mod; } return ans ; } int main(){ int T; scanf("%d",&T); while( T-- ){ scanf("%s",s); LL len = strlen(s); LL m = mod - 1
; LL id = s[0]-'0'; for( LL i = 1 ; i < len ; i++ ){ id = ( id * 10 + ( s[i] - '0' ) ) % m; } printf("%lld\n",quick(2,id-1)); } return 0; }

L 思路 :可以得到有7種長度為3的情況不能使用, 長度為2共有9種,cf , cm , mc , mf , fc , fm , ff, mm , cc 在加一個長度時,得到的合法情況數量分別為,2 2 2 3 2 3 2 2 2 以後每增加一個時就是再重複此過程,根據對應關係寫一個9*9矩陣。 用矩陣快速冪計算。 Code:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int mod = 1e9+7;
int t ; 
ll n ;
struct Matrix{
    ll m[9][9];
    Matrix(){
        memset(m, 0, sizeof(m));
    }
};

Matrix mul( Matrix &A, Matrix &B ) {
    Matrix C;
    for(int i = 0; i < 9; i++) {
        for(int j = 0; j < 9; j ++) {
            for(int k = 0; k < 9; k ++) {
                C.m[i][j] = (C.m[i][j] + A.m[i][k]*B.m[k][j]) % mod;
            }
        }
    }
    return C;
}

Matrix pow( Matrix A, ll n ) {
    Matrix B;
    for(int i = 0; i < 9; i ++) B.m[i][i] = 1;
    while( n ) {
        if( n & 1 ) B = mul(B, A);
        A = mul(A, A);
        n >>= 1;
    }
    return B;
}
int main() {
    Matrix A;
    A.m[0][5] = A.m[0][7] = A.m[1][3] = A.m[1][5] = A.m[1][7] = 1;
    A.m[2][4] = A.m[2][6] = A.m[3][0] = A.m[3][6] = 1;
    A.m[4][1] = A.m[4][8] = A.m[5][1] = A.m[5][2] = A.m[5][8] = 1;
    A.m[6][0] = A.m[6][4] = A.m[7][3] = A.m[7][5] = A.m[8][1] = A.m[8][2] = 1;
    int T;
    scanf("%d",&T);
    while( T -- ){
        scanf("%lld", &n);
        if( n == 1 ) {
            printf("3\n");
            continue ;
        }
        Matrix B = pow( A , n - 2 );
        ll ans = 0LL;
        for( int i = 0 ; i < 9 ; i++ ){
            for( int j = 0 ; j < 9 ; j++ ){
                ans = ( ans + B.m[i][j] ) % mod ;
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}