A : 斐波那契数列
题目描述
斐波那契数列的定义如下:
给出 n,pn,p ,求出 f(n)%pf(n)%p 的值。
输入格式
第一行一个数 T(1\le T\le 100)T(1≤T≤100),表示数据组数。
接下来 TT 行,每行两个整数 n,p(1\le n\le 109,108\le p\le 10^9)n,p(1≤n≤10
9
,10
8
≤p≤10
9
)。
输出格式
输出 TT 行,表示每组数据的答案。
Case 1
Input
6
1 998244353
2 998244353
3 998244353
4 998244353
5 998244353
1000000000 998244353
Output
1
1
2
3
5
990450892
#include<iostream>
using namespace std;
long long mod;
class Mat{
public:
long long m[2][2];
Mat(int _a, int _b, int _c, int _d) {
m[0][0] = _a; m[0][1] = _b;
m[1][0] = _c; m[1][1] = _d;
}
};
Mat multi(Mat& a,Mat& b) {
Mat t(0, 0, 0, 0);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
t.m[i][j] = t.m[i][j] + a.m[i][k] * b.m[k][j];
t.m[i][j] %= mod;
}
}
}
return t;
}
long long pow(long long p) {
Mat t(1, 0, 0, 1);
Mat c(1, 1, 1, 0);
while (p) {
if (p & 1)t = multi(t, c);
c = multi(c, c);
p /= 2;
}
return t.m[0][1];
}
int main() {
int T;
cin >> T;
while (T--) {
int n;
cin >> n >> mod;
long long ans = pow(n);
cout << ans << endl;
}
return 0;
}
B : 自然数幂和
题目描述
给定 𝑛 和 𝑘,计算 \Sigma{n}_{i=1}ikΣ
i=1
n
i
k
对 10^9+710
9
+7 取模的结果。
输入格式
第一行一个数 T(1\le T\le 100)T(1≤T≤100),表示数据组数。
接下来 TT 行,每行两个整数 n,k(1\le n\le 10^9,1\le k\le 10)n,k(1≤n≤10
9
,1≤k≤10)。
输出格式
输出 TT 行,表示每组数据的答案。
Case 1
Input
6
1 10
2 2
2 3
3 2
3 3
1000000000 9
Output
1
5
9
14
36
12313161
#include<iostream>
#include<string.h>
#include<math.h>
using namespace std;
int n;//矩阵维数
struct Mat {
long long m[101][101];
void ini() {
memset(m, 0, sizeof(m));
}
void ini_dw() {
memset(m, 0, sizeof(m));
for (int i = 0; i < n; i++)m[i][i] = 1;
}
};
int mod=1e9+7;//模
Mat a, e;//a是输入矩阵 e是单位矩阵
Mat multi(Mat a, Mat b) {
Mat c;
c.ini();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < n; k++) {
c.m[i][j] = ((c.m[i][j] % mod) + (a.m[i][k] * b.m[k][j]) % mod) % mod;
}
}
}
return c;
}
Mat pow(Mat x, long long y) {
Mat ans;
ans.ini_dw();
//if (y == 0 )return ans;
//if(y==1)return x;
while (y) {
if (y & 1)ans = multi(ans, x);
x = multi(x, x);
y /= 2;
}
return ans;
}
long long C(int n, int m)//排列函数即C 的个数
{
if (n < m)return C(m, n);
long long i, c = 1;
i = m;
while (i != 0)
{
c *= n; n--; i--;
}
while (m != 0)
{
c /= m; m--;
}
return c;
}
long long fastPower(long long base, long long power) {
long long result = 1;
while (power > 0) {
if (power & 1) {//此处等价于if(power%2==1)
result = result * base % 1000;
}
power >>= 1;//此处等价于power=power/2
base = (base * base) % 1000;
}
return result;
}
int main() {
int T;
cin >> T;
while (T--) {
int m, k;
cin >> m >> k;
n = k + 2;
Mat t;
t.ini();
t.m[0][0]=1;
for(int i=1;i<n;i++)t.m[0][i]=C(k,i-1);
for(int i=1;i<n;i++){
for(int j=0;j<n;j++){
if(i==j)t.m[i][j]=1;
else if(i>j)t.m[i][j]=0;
else if(i<j)t.m[i][j]=C(k+1-i,j-i);
}
}
long long res[11];
t = pow(t, m - 1);
long long ans = 0;
for (int i = 0; i < k + 2; i++) {
ans = (ans+t.m[0][i])%mod;
}
cout <<ans << endl;
}
return 0;
}
C : R??G??B??
题目描述
msy 的“显示器”终于完工啦!但是由于设计出了问题,这个“显示器”存在一个严重的 bug,就是每个像素同时只能显示红色、绿色、蓝色其中的一种颜色。msy 感觉一个学期白忙活了,但是又不能浪费材料,于是他觉得把这个有问题的“显示器”作为装饰。msy 喜欢蓝色和绿色,同时也喜欢偶数,因此他希望“显示器”的每一帧都同时包含偶数个蓝色像素和偶数个绿色像素。此时 msy 想知道,他可以看到多少不同的帧?
由于答案可能很大,你只需输出答案对 998244353998244353 取模的结果即可。
输入格式
第一行一个数 T(1\le T\le 100)T(1≤T≤100),表示数据组数。
接下来 TT 行,每行一个整数 n(1\le n\le 10^9)n(1≤n≤10
9
),表示“显示器”上的像素个数。
输出格式
输出 TT 行,表示每组数据的答案。
Case 1
Input
6
1
2
3
4
5
1000000000
Output
1
3
7
21
61
224965630
#include<iostream>
#include<string.h>
#include<math.h>
using namespace std;
int n=3;//矩阵维数
struct Mat {
long long m[101][101];
void ini() {
memset(m, 0, sizeof(m));
}
void ini_dw() {
memset(m, 0, sizeof(m));
for (int i = 0; i < n; i++)m[i][i] = 1;
}
};
int mod = 998244353;//模
Mat a, e;//a是输入矩阵 e是单位矩阵
Mat multi(Mat a, Mat b) {
Mat c;
c.ini();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < n; k++) {
c.m[i][j] = ((c.m[i][j] % mod) + (a.m[i][k] * b.m[k][j]) % mod) % mod;
}
}
}
return c;
}
Mat pow(Mat x, long long y) {
Mat ans;
ans.ini_dw();
if (y == 0 )return ans;
if (y == 1)return x;
while (y) {
if (y & 1)ans = multi(ans, x);
x = multi(x, x);
y /= 2;
}
return ans;
}
int main() {
int T;
cin >> T;
while (T--) {
int m;
cin >> m;
/*if (m == 2) {
cout << 3 << endl;
continue;
}*/
Mat t;
t.m[0][0] = 1; t.m[0][1] = 0; t.m[0][2] = 1;
t.m[1][0] = 0; t.m[1][1] = 1; t.m[1][2] = 1;
t.m[2][0] = 2; t.m[2][1] = 2; t.m[2][2] = 1;
t = pow(t, m - 1);
long long ans = 0;
ans = (ans%mod + t.m[0][0]%mod + (t.m[0][2] * 2)%mod) % mod;
cout << ans << endl;
}
return 0;
}
D : 衣柜
题目描述
ZJM 有 mm 件衬衫,现一共有 nn 天。
如果 ZJM 昨天穿衬衫 AA,今天穿衬衫 BB,则他今天可以获得 H[A][B]H[A][B] 快乐值。
询问 nn 天过后,ZJM 最多可以获得多少快乐值?
输入格式
第一行两个数 n,m(2\le n\le 10^8, 1\le m\le 100)n,m(2≤n≤10
8
,1≤m≤100),表示总天数和衬衫数量。
接下来 mm 行,每行 mm 个数,第 ii 行的第 jj 个数表示 H[i][j](0\le H[i][j]\le 10^6)H[i][j](0≤H[i][j]≤10
6
),即昨天穿衬衫 ii,今天穿衬衫 jj 可以获得的快乐值。
输出格式
输出一个数表示答案。
Case 1
Input
3 2
0 1
1 0
Output
2
#include<iostream>
#include<string.h>
#include<math.h>
using namespace std;
int n;//矩阵维数
struct Mat {
long long m[101][101];
void ini() {
memset(m, 0, sizeof(m));
}
void ini_dw() {
memset(m, 0, sizeof(m));
for (int i = 0; i < n; i++)m[i][i] = 1;
}
};
Mat multi(Mat a, Mat b) {
Mat c;
c.ini();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < n; k++) {
c.m[i][j] = max(c.m[i][j],a.m[i][k] + b.m[k][j]);
}
}
}
return c;
}
Mat pow(Mat x, long long y) {
Mat ans;
ans.ini_dw();
ans = x;
while (y) {
if (y & 1)ans = multi(ans, x);
x = multi(x, x);
y /= 2;
}
return ans;
}
int main() {
int m;
cin >> m >> n;
Mat t;
t.ini();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> t.m[i][j];
}
}
t = pow(t, m-2);
long long ans = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
ans = max(ans, t.m[i][j]);
}
}
cout << ans << endl;
}
思路
不会太难的地方,但是有和去年差不多的题目,斐波那契这题网上好多解释,自己改改就行了。
其他题可以看看扩展资料
这里是资料
里面例题能学到一些东西,但是自己做还是有差距的,挺多地方得看着别人的代码想。
主要讲了字典树和KMP还有哈希,都没啥时间去理解了,赶紧准备考试了。希望能做出来两道题。