A.Lucky(HDU5665)
思路
题目问在题给数集的每个数都能使用无限次的情况下,能否通过令数集中某些数相加的方法得到全体自然数。根据百度百科的说法,自然数的定义有争议。在数学领域中,自然数从
1
开始,在计算机科学领域中,自然数从
代码
#include <cstdio>
bool zero, one;
int t, n, a;
int main() {
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
zero = one = false;
for(int i = 0; i < n; i++) {
scanf("%d", &a);
if(a == 0) {
zero = true;
}
if(a == 1) {
one = true;
}
}
puts(zero && one ? "YES" : "NO");
}
return 0;
}
B.Segment(HDU5666)
思路
先不考虑取模的情况。当
q=3
时,满足等式约数的
(x,y)
为
(0,3),(1,2),(1,1),(2,1),(3,0),(0,0),(1,0),(0,1)
,而不在边界上的点只有
(1,1)
。同理当
q=4
时,满足条件的
(x,y)
为
(1,1),(1,2),(2,1)
。不难发现,对任意的
x∈[1,q−1]
,满足条件的
(x,y)
为
(x,1),(x,2),...,(x,q−x−1)
。根据数列求和公式,有
ans=(q−1)∗(q−2)2
。由于
q
非常大,这里直接让
代码
#include <cstdio>
typedef long long ll;
ll t, b, m, x, y, ans;
ll modMul(ll a, ll b, ll m) {
ll ans = 0;
for(; b > 0; b >>= 1) {
if (b & 1) {
ans = (ans + a) % m;
}
a = (a << 1) % m;
}
return ans;
}
int main() {
scanf("%I64d", &t);
while(t--) {
scanf("%I64d%I64d", &b, &m);
if(b <= 2) {
puts("0");
continue;
}
x = b - 1;
y = b - 2;
if(x % 2 == 0) {
x /= 2;
}
if(y % 2 == 0) {
y /= 2;
}
printf("%I64d\n", modMul(x, y, m));
}
return 0;
}
C.Sequence(HDU5667)
思路
由于题目直接给出了递推式,因此这是个递推的题目。根据题意可以直接写出前几项,结果发现(其实可以直接观察出来)数列
fn
的每一项都是以
a
为底的幂函数式。于是可以只研究它们的幂。为了方便设
gn=⎧⎩⎨0,1,cgn−1+gn−2+b,n=1n=2otherwise
将 n>2 的情况用矩阵来表示可以写成
⎛⎝⎜gngn−11⎞⎠⎟=⎛⎝⎜c10100b01⎞⎠⎟×⎛⎝⎜gn−1gn−21⎞⎠⎟
然后就用矩阵快速幂便能够快速地求出
gn
了。但是遗憾的是
gn
非常大不能直接求,但是非常幸运,我们求出的
gn
是
a
的幂,而
ap−1=1(modp)
可以得到降幂公式
akmodp=akmod(p−1)+(p−1)modp
其中的 +(p−1) 是用来防止 bmod(p−1)=0 的。
综上所述,最终的答案为
agnmod(p−1)+(p−1)modp 。
代码
#include <iostream>
#include <cstring>
using namespace std;
typedef unsigned long long ll;
ll t, n, m, a, b, c, p;
// 矩阵结构体
struct matrix {
int n, m;
ll a[5][5];
matrix(int n = 3, int m = 3): n(n), m(m) {
memset(a, 0, sizeof(a));
}
// 矩阵模乘
matrix mod_mul(matrix &b, ll mod) const {
matrix tmp(n, b.m);
for(int i = 0; i < n; i++) {
for(int j = 0; j < b.m; j++) {
for(int k = 0; k < m; k++) {
tmp.a[i][j] = (tmp.a[i][j] + a[i][k] * b.a[k][j] % mod) % mod;
}
}
}
return tmp;
}
// 矩阵取模快速幂
matrix mod_pow(ll nn, ll mod) const {
matrix a = *this, tmp(n, n);
for(int i = 0; i < n; i++) {
tmp.a[i][i] = 1;
}
for(; nn > 0; nn >>= 1) {
if(nn & 1) {
tmp = tmp.mod_mul(a, mod);
}
a = a.mod_mul(a, mod);
}
return tmp;
}
};
// 快速幂函数
ll modPow(ll a, ll n, ll mod) {
ll ans = 1;
for(; n > 0; n >>= 1) {
if(n & 1) ans = (ans * a) % mod;
a = (a * a) % mod;
}
return ans;
};
int main() {
matrix mat, res;
mat.a[0][1] = mat.a[1][0] = mat.a[2][2] = 1;
cin >> t;
while(t--) {
cin >> n >> a >> b >> c >> m;
if(n == 1) {
cout << 1 << endl;
continue;
}
if(n == 2) {
cout << modPow(a, b, m) << endl;
continue;
}
// 填充矩阵
mat.a[0][2] = b;
mat.a[0][0] = c;
// 矩阵快速幂求g(n)
res = mat.mod_pow(n - 2, m - 1);
// 费马小定理
p = (b * res.a[0][0] + res.a[0][2]) % (m - 1) + m - 1;
// 快速幂求结果
cout << modPow(a, p, m) << endl;
}
return 0;
}