64位整数乘法 [https://www.acwing.com/problem/content/92/]
sol:
将 b 进行二进制拆分,就变成了计算$a*(2^0 + 2^1 + 2^2 +....) $,结合乘法分配律,对每一项进行相加,得到结果。 (O(logN))
LL mul(LL a, LL b, LL p) {
LL res = 0;
for(; b; b >>= 1) {
if( b & 1)
res = (res + a) % p;
a = 2 * a % p;
}
return res;
}
费解的开关 [https://www.acwing.com/problem/content/description/97/]
sol:
类似于这一道题目[https://www.luogu.com.cn/problem/CF1239A],CF的这道题是确定第一行和第一列之后所有的状态都确定了。而本题是确定了第一行的状态就
可以推出剩下的开关状态。我却没有想到,原因是我没有考虑到一个性质,就是按开关的顺序是无关的。所以我们可以枚举第一行的所有状态,从而推出所有状态。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 10;
int R = 5;
int a[N][N], b[N][N];
char s[N][N];
void FilpBit(int x, int y) {
a[x][y] ^= 1;
a[x + 1][y] ^= 1;
a[x - 1][y] ^= 1;
a[x][y + 1] ^= 1;
a[x][y - 1] ^= 1;
}
int allLight() {
int cnt = 0;
for(int i = 2; i <= R; i ++) {
for(int j = 1; j <= R; j ++) {
if(a[i - 1][j] == 0) {
FilpBit(i, j);
cnt ++;
}
}
if( i == R) {
for(int j = 1; j <= R; j ++) {
if( a[i][j] != 1) return 7;
}
}
}
return cnt;
}
int main()
{
int T;
scanf("%d", &T);
while(T --) {
int ans = 7;
for(int i = 1; i <= R; i ++) {
scanf("%s", s[i] + 1);
for(int j = 1; j <= R; j ++) {
a[i][j] = s[i][j] - '0';
b[i][j] = a[i][j];
}
}
for(int s = 0; s < (1 << R); s ++) {
int cnt = 0;
for(int k = 0; k < R; k ++) {
if( (s >> k) & 1) {
FilpBit(1, k + 1);
cnt ++;
}
}
ans = min(allLight() + cnt, ans);
memcpy(a, b, sizeof(b));
}
if( ans > 6) ans = -1;
printf("%d
", ans);
}
return 0;
}
约数之和 [https://www.acwing.com/problem/content/99/]
sol:
首先利用约数个数和定理,可以得到,题目就是等比数列求和。可以用分治来解决。分类讨论,B为偶数和B为奇数。
设(f(n) = sum_{i = 0}^{n}A^i)
再结合快速幂,f(n)就可以由f(n/2)递推过来了。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N = 100, mod = 9901;
typedef long long LL;
int p[N], cnt;
LL r[N];
void divide(int n) {
for(int i = 2; i * i <= n; i ++) {
if( n % i == 0) {
int t = 0;
p[++cnt] = i;
while(n % i == 0) {
n /= i;
t ++;
}
r[cnt] = t;
}
}
if( n > 1) {
p[++cnt] = n;
r[cnt] = 1;
}
}
LL qmi(LL a, LL b) {
LL res = 1;
for(; b; b >>= 1) {
if(b & 1)
res = res * a % mod;
a = a * a % mod;
}
return res;
}
LL solve(LL a, LL b) {
if( b == 0)
return 1ll;
LL t = solve(a, b / 2);
if( b % 2 == 1) {
LL tmp = (qmi(a, (b + 1) / 2) + 1 ) * t % mod;
return tmp;
} else {
LL tmp = ( qmi(a, b / 2) * (t - 1) % mod + t % mod) % mod;
return tmp;
}
}
int main()
{
int a, b;
LL ans = 1;
scanf("%d%d", &a, &b);
divide(a);
for(int i = 1; i <= cnt; i ++) {
r[i] *= b;
ans = ans * solve((LL)p[i], r[i]) % mod;
}
if(a == 0)
ans = 0;
printf("%lld
", ans);
return 0;
}