ACM-ICPC 2018 焦作賽區網路預賽 G 隔板+費馬小定理 L矩陣快速冪
阿新 • • 發佈:2018-12-10
思路:隔板法知道結果是 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;
}