A : 斐波那契数列
题目描述
斐波那契数列的定义如下:
给出 n,p ,求出 f(n)%p 的值。
输入格式
第一行一个数 T(1≤T≤100),表示数据组数。
接下来 T 行,每行两个整数 n,p(1≤n≤109,108≤p≤109)。
输出格式
输出 T 行,表示每组数据的答案。
测试样例
样例 1
输入:
6
1 998244353
2 998244353
3 998244353
4 998244353
5 998244353
1000000000 998244353
输出:
1
1
2
3
5
990450892
解答
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll T;
ll n, p;
ll sum;
struct Matrix{
ll x[2][2];
Matrix operator*(const Matrix &t)const{
Matrix ret;
for (ll i = 0; i < 2;i++){
for (ll j = 0; j < 2;j++){
ret.x[i][j] = 0;
for (ll k = 0; k < 2;k++){
ret.x[i][j] += x[i][k] * t.x[k][j] % p;
ret.x[i][j] %= p;
}
}
}
return ret;
}
Matrix() { memset(x, 0, sizeof x); }
Matrix(const Matrix &t) { memcpy(x, t.x, sizeof x); }
};
Matrix quick_pow(Matrix a, ll x){
Matrix ret;
ret.x[0][0] = ret.x[1][1] = 1;
ret.x[0][1] = ret.x[1][0] = 0;
while(x){
if(x&1){
ret = ret*a;
}
a = a * a;
x >>= 1;
}
return ret;
}
int main(){
// freopen("3.in", "r", stdin);
// freopen("3.out", "w", stdout);
cin >> T;
while(T--){
sum = 0;
cin >> n >> p;
Matrix a;
a.x[0][0] = a.x[0][1] = a.x[1][0] = 1;
a.x[1][1] = 0;
if(n == 1 or n==2){
cout << 1 << "\n";
}else{
a = quick_pow(a, n - 2);
sum = (a.x[0][0] + a.x[1][0]) % p;
cout << sum << "\n";
}
// for (ll i = 1; i <= n - 2;i++){
// }
}
return 0;
}
B : 自然数幂和
题目描述
给定 𝑛 和 𝑘,计算 Σi=1nik 对 109+7 取模的结果。
输入格式
第一行一个数 T(1≤T≤100),表示数据组数。
接下来 T 行,每行两个整数 n,k(1≤n≤109,1≤k≤10)。
输出格式
输出 T 行,表示每组数据的答案。
测试样例
样例 1
输入:
6
1 10
2 2
2 3
3 2
3 3
1000000000 9
输出:
1
5
9
14
36
12313161
解答
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll T, n, k;
int N=20;
ll p = 1e9 + 7;
ll result;
struct Matrix{
ll x[20][20];
Matrix operator*(const Matrix &t)const{
Matrix ret;
for (ll i = 0; i < N;i++){
for (ll j = 0; j < N;j++){
ret.x[i][j] = 0;
for (ll k = 0; k < N;k++){
ret.x[i][j] += x[i][k] * t.x[k][j] % p;
ret.x[i][j] %= p;
}
}
}
return ret;
}
Matrix() { memset(x, 0, sizeof x); }
Matrix(const Matrix &t) { memcpy(x, t.x, sizeof x); }
};
Matrix quick_pow(Matrix a, ll x){
Matrix ret;
for (int i = 0; i < N;i++){
for (int j = 0; j < N;j++){
if(i==j){
ret.x[i][j] = 1;
}else{
ret.x[i][j] = 0;
}
}
}
while (x)
{
if (x & 1)
{
ret = ret * a;
}
a = a * a;
x >>= 1;
}
return ret;
}
ll chengji(ll x){
ll sum = 1;
if(x == 0){
return 1;
}
for (int i = 1; i <= x;i++){
sum *= i;
}
return sum;
}
int main(){
cin >> T;
while(T--){
result = 0;
cin >> n >> k;
// N = k + 3;
Matrix a;
for (int i = 0; i < k+2;i++){
for (int j = 0; j < k+2;j++){
if(i == j and i == 0){
a.x[i][j] = 1;
}else{
if(i == 0){
a.x[i][j] = chengji(k) / (chengji(j - 1) * chengji(k - j + 1));
}else{
if(j < i){
a.x[i][j] = 0;
}else{
if(k-i+1 == 1){
a.x[i][j] = 1;
}else if(k-i+1==0){
a.x[i][j] = 1;
}else{
a.x[i][j] = chengji(k - i + 1) / (chengji(j - i) * chengji(k + 1 - j));
}
}
}
}
}
}
a = quick_pow(a, n - 1);
for (int i = 0; i < k+2;i++){
result += a.x[0][i]%p;
result %= p;
}
cout << result%p << "\n";
}
return 0;
}
C : R??G??B??
题目描述
msy 的“显示器”终于完工啦!但是由于设计出了问题,这个“显示器”存在一个严重的 bug,就是每个像素同时只能显示红色、绿色、蓝色其中的一种颜色。msy 感觉一个学期白忙活了,但是又不能浪费材料,于是他觉得把这个有问题的“显示器”作为装饰。msy 喜欢蓝色和绿色,同时也喜欢偶数,因此他希望“显示器”的每一帧都同时包含偶数个蓝色像素和偶数个绿色像素。此时 msy 想知道,他可以看到多少不同的帧?
由于答案可能很大,你只需输出答案对 998244353 取模的结果即可。
输入格式
第一行一个数 T(1≤T≤100),表示数据组数。
接下来 T 行,每行一个整数 n(1≤n≤109),表示“显示器”上的像素个数。
输出格式
输出 T 行,表示每组数据的答案。
测试样例
样例 1
输入:
6
1
2
3
4
5
1000000000
输出:
1
3
7
21
61
224965630
解答
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll p = 998244353;
ll T, n;
const int N = 3;
struct Matrix{
ll x[3][3];
Matrix operator*(const Matrix &t)const{
Matrix ret;
for (ll i = 0; i < N;i++){
for (ll j = 0; j < N;j++){
ret.x[i][j] = 0;
for (ll k = 0; k < N;k++){
ret.x[i][j] += x[i][k] * t.x[k][j] % p;
ret.x[i][j] %= p;
}
}
}
return ret;
}
Matrix() { memset(x, 0, sizeof x); }
Matrix(const Matrix &t) { memcpy(x, t.x, sizeof x); }
};
Matrix quick_pow(Matrix a, ll x){
Matrix ret;
for (int i = 0; i < N;i++){
for (int j = 0; j < N;j++){
if(i==j){
ret.x[i][j] = 1;
}else{
ret.x[i][j] = 0;
}
}
}
while (x)
{
if (x & 1)
{
ret = ret * a;
}
a = a * a;
x >>= 1;
}
return ret;
}
int main(){
cin >> T;
while(T--){
cin >> n;
Matrix a;
a.x[0][0] = a.x[0][2] = a.x[1][1] = a.x[1][2] = a.x[2][2] = 1;
a.x[0][1] = a.x[1][0] = 0;
a.x[2][0] = a.x[2][1] = 2;
a = quick_pow(a, n - 1);
ll sum = ((a.x[0][0])%p + (a.x[0][2]*2)%p) % p;
cout << sum << "\n";
}
return 0;
}
D : 衣柜
题目描述
ZJM 有 m 件衬衫,现一共有 n 天。
如果 ZJM 昨天穿衬衫 A,今天穿衬衫 B,则他今天可以获得 H[A][B] 快乐值。
询问 n 天过后,ZJM 最多可以获得多少快乐值?
输入格式
第一行两个数 n,m(2≤n≤108,1≤m≤100),表示总天数和衬衫数量。
接下来 m 行,每行 m 个数,第 i 行的第 j 个数表示 H[i][j](0≤H[i][j]≤106),即昨天穿衬衫 i,今天穿衬衫 j 可以获得的快乐值。
输出格式
输出一个数表示答案。
测试样例
样例 1
输入:
3 2
0 1
1 0
输出:
2
解答
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n, m;
ll f[110][110];
ll H[110][110];
const ll N = 110;
struct Matrix{
ll x[110][110];
Matrix operator*(const Matrix &t)const{
Matrix ret;
for (ll i = 0; i < N;i++){
for (ll j = 0; j < N;j++){
ret.x[i][j] = 0;
for (ll k = 0; k < N;k++){
ret.x[i][j] = max(x[i][k] + t.x[k][j],ret.x[i][j]);
// ret.x[i][j] %= p;
}
}
}
return ret;
}
Matrix() { memset(x, 0, sizeof x); }
Matrix(const Matrix &t) { memcpy(x, t.x, sizeof x); }
};
Matrix quick_pow(Matrix a, ll x){
Matrix ret;
ret = a;
// for (int i = 0; i < N;i++){
// for (int j = 0; j < N;j++){
// if(i==j){
// ret.x[i][j] = 1;
// }else{
// ret.x[i][j] = 0;
// }
// }
// }
while (x)
{
if (x & 1)
{
ret = ret * a;
}
a = a * a;
x >>= 1;
}
return ret;
}
int main(){
cin>>n>>m;
for (int i = 1; i <= m;i++){
for (int j = 1; j <= m;j++){
cin >> H[i][j];
}
}
Matrix a;
for (int i = 0; i < m;i++){
for (int j = 0; j < m;j++){
a.x[i][j] = H[j + 1][i+1];
}
}
a = quick_pow(a, n - 2);
ll sum = 0;
for (int i = 0; i < m;i++){
for (int j = 0; j < m;j++){
if(sum<a.x[i][j])
sum = a.x[i][j];
}
}
cout << sum << "\n";
return 0;
}