位运算-递归-递推
90 64位整数乘法
快速幂 : 乘法 实现 乘方
快速加 : 加法 实现 乘法
C++ 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #include <cstdio>
typedef long long LL ;
LL qadd ( LL a , LL b , LL p )
{
LL res = 0 ;
while ( b )
{
if ( b & 1 ) res = ( res + a ) % p ;
a = ( a + a ) % p ;
b >>= 1 ;
}
return res ;
}
int main ()
{
LL a , b , p ;
scanf ( "%lld%lld%lld" , & a , & b , & p );
printf ( "%lld \n " , qadd ( a , b , p ));
return 0 ;
}
95 费解的开关
题面:
你玩过“拉灯”游戏吗?
25 盏灯排成一个 5×5 的方形。
每一个灯都有一个开关,游戏者可以改变它的状态。
每一步,游戏者可以改变某一个灯的状态。
游戏者改变一个灯的状态会产生连锁反应:和这个灯上下左右相邻的灯也要相应地改变其状态。
我们用数字 1 表示一盏开着的灯,用数字 0 表示关着的灯。
分析:
C++ 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 #include <cstdio>
#include <cstring>
using namespace std ;
const int N = 6 ;
char g [ N ][ N ], bg [ N ][ N ];
int dx [ 5 ] = { -1 , 0 , 1 , 0 , 0 }, dy [ 5 ] = { 0 , 1 , 0 , -1 , 0 };
void turn ( int x , int y ) // 按一下第x行第y列的开关
{
for ( int i = 0 ; i < 5 ; i ++ )
{
int a = x + dx [ i ], b = y + dy [ i ];
if ( a < 0 || a >= 5 || b < 0 || b >= 5 ) continue ;
g [ a ][ b ] ^= 1 ;
}
}
int main ()
{
int T ;
scanf ( "%d" , & T );
while ( T -- )
{
for ( int i = 0 ; i < 5 ; i ++ ) scanf ( "%s" , bg [ i ]);
int res = 10 ;
for ( int op = 0 ; op < 32 ; op ++ )
{
int cnt = 0 ;
memcpy ( g , bg , sizeof g );
// 操作第一行的开关
for ( int i = 0 ; i < 5 ; i ++ )
if ( op >> i & 1 )
{
turn ( 0 , i );
cnt ++ ;
}
// 递推出第1~4行开关的状态
for ( int i = 0 ; i < 4 ; i ++ )
for ( int j = 0 ; j < 5 ; j ++ )
if ( g [ i ][ j ] == '0' )
{
turn ( i + 1 , j );
cnt ++ ;
}
// 检查最后一行灯是否全亮
bool success = true ;
for ( int i = 0 ; i < 5 ; i ++ )
if ( g [ 4 ][ i ] == '0' )
success = false ;
if ( success && res > cnt ) res = cnt ;
}
if ( res > 6 ) res = -1 ;
printf ( "%d \n " , res );
}
return 0 ;
}
为什么这里要bg?
97 约数之和
假设现在有两个自然数 A 和 B,S 是 \(A^B\) 的所有约数之和。
请你求出 \(S\mod9901\) 的值是多少。
方法1: 公式 快速幂 逆元
方法2: 递推公式
C++ 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 #include <cstdio>
const int mod = 9901 ;
int qmi ( int a , int k ) // 快速幂模板: a^k
{
int res = 1 ;
a %= mod ;
while ( k )
{
if ( k & 1 ) res = res * a % mod ;
a = a * a % mod ;
k >>= 1 ;
}
return res ;
}
int sum ( int p , int k ) // 递推公式
{
if ( k == 1 ) return 1 ;
if ( k % 2 == 0 ) return ( 1 + qmi ( p , k / 2 )) * sum ( p , k / 2 ) % mod ;
return ( sum ( p , k - 1 ) + qmi ( p , k - 1 )) % mod ;
}
int main ()
{
int a , b ;
scanf ( "%d%d" , & a , & b );
int res = 1 ;
// 对a分解质因数: 纯模板, 试除法
for ( int i = 2 ; i * i <= a ; i ++ )
if ( a % i == 0 )
{
int s = 0 ;
while ( a % i == 0 )
{
a /= i , s ++ ;
}
res = res * sum ( i , b * s + 1 ) % mod ;
}
if ( a > 1 ) res = res * sum ( a , b + 1 ) % mod ;
if ( a == 0 ) res = 0 ;
printf ( "%d \n " , res );
return 0 ;
}
98 分形之城
C++ 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 #include <cstdio>
#include <cstring>
#include <cmath>
typedef long long LL ;
struct Point
{
LL x , y ;
};
Point get ( LL n , LL a )
{
if ( n == 0 ) return { 0 , 0 };
// block size = 2^{2n-2}
// 1ll: long long 类型的 1
LL block = 1l l << n * 2 - 2 , len = 1l l << n - 1 ;
auto p = get ( n - 1 , a % block );
LL x = p . x , y = p . y ;
int z = a / block ;
if ( z == 0 ) return { y , x };
else if ( z == 1 ) return { x , y + len };
else if ( z == 2 ) return { x + len , y + len };
return { len * 2 - 1 - y , len - 1 - x };
}
int main ()
{
int T ;
scanf ( "%d" , & T );
while ( T -- )
{
LL n , a , b ;
scanf ( "%lld%lld%lld" , & n , & a , & b );
auto pa = get ( n , a - 1 );
auto pb = get ( n , b - 1 );
double dx = pa . x - pb . x , dy = pa . y - pb . y ;
printf ( "%.0lf \n " , sqrt ( dx * dx + dy * dy ) * 10 );
}
return 0 ;
}