进制转换
4376. 数圈圈
———10->16
十六进制是一种基数为 16 的计数系统,是一种逢 16 进 1 的进位制。
通常用数字 0、1、2、3、4、5、6、7、8、9 和字母 A、B、C、D、E、F 表示,其中: A∼F 表示 10∼15,这些称作十六进制数字。
观察这些数字的图案,我们可以发现,有些数字上面包含圈圈,具体来说:
数字 0,4,6,9,A,D 中包含一个圈。
数字 8,B 中包含两个圈。
数字 1,2,3,5,7,C,E,F 中不含圈。
现在,给定一个十进制整数 n,请你将其转化为十六进制表示,并数一数其十六进制表示中一共含有多少个圈圈。
输入格式
一个整数 n。
输出格式
一个整数,表示整数 n 的十六进制表示包含的圈圈总数。
数据范围
前三个测试点满足 0≤n≤100,
所有测试点满足 0≤n≤2×10^9。
输入样例1:
11
输出样例1:
2
输入样例2:
14
输出样例2:
0
#include <iostream>#include <cstring>#include <algorithm>using namespace std;int n;int get(int x,int){if(x>=0&&x<=9){return x+'0';}else{return 'A'+x-10;}}string get(int x){string res="";if(x==0){ // 必须单独处理一下 0return "0";}while(x){res+=get(x%16,0);x/=16;}return res;}int cal(string s){int res=0;for (int i = 0; i < s.size(); i ++ ){if(s[i]=='0'||s[i]=='4'||s[i]=='6'||s[i]=='9'||s[i]=='A'||s[i]=='D'){res++;}else if(s[i]=='8'||s[i]=='B'){res+=2;}}return res;}int main(){cin >> n;string s = get(n);cout << cal(s);}
质数
866. 试除法判定质数
给定 n 个正整数 ai,判定每个数是否是质数。
输入格式
第一行包含整数 n。
接下来 n 行,每行包含一个正整数 ai。
输出格式
共 n 行,其中第 i 行输出第 i 个正整数 ai 是否为质数,是则输出 Yes,否则输出 No。
输入样例:
2 2 6
输出样例:
Yes No
#include <iostream>#include <cstring>#include <algorithm>using namespace std;bool is_prime(int n){if(n<2){return false;}for (int i = 2; i <= n/i; i ++ ){if(n%i==0){return false;}}return true;}int main(){int n;cin >> n;for (int i = 0; i < n; i ++ ){int x;cin >> x;if(is_prime(x)){cout << "Yes"<<endl;}else{cout << "No" <<endl;}}}
867. 分解质因数
给定 nn 个正整数 aiai,将每个数分解质因数,并按照质因数从小到大的顺序输出每个质因数的底数和指数。
输入格式
第一行包含整数 nn。
接下来 nn 行,每行包含一个正整数 aiai。
输出格式
对于每个正整数 aiai,按照从小到大的顺序输出其分解质因数后,每个质因数的底数和指数,每个底数和指数占一行。
每个正整数的质因数全部输出完毕后,输出一个空行。
输入样例:
2 6 8
输出样例:
2 1 3 1
2 3

#include <iostream>#include <algorithm>using namespace std;void divide(int x){for (int i = 2; i <= x / i; i ++ )if (x % i == 0){int s = 0;while (x % i == 0) x /= i, s ++ ;cout << i << ' ' << s << endl;}if (x > 1) cout << x << ' ' << 1 << endl;cout << endl;}int main(){int n;cin >> n;while (n -- ){int x;cin >> x;divide(x);}return 0;}
868. 筛质数
给定一个正整数 n,请你求出 1∼n 中质数的个数。
输入格式
共一行,包含整数 n。
输出格式
共一行,包含一个整数,表示 1∼n 中质数的个数。
输入样例:
8
输出样例:
4
#include <iostream>#include <algorithm>using namespace std;const int N= 1000010;int primes[N], cnt;bool st[N];void get_primes(int n){for (int i = 2; i <= n; i ++ ){if (!st[i]) primes[cnt ++ ] = i;for (int j = 0; primes[j] <= n / i; j ++ ){st[primes[j] * i] = true;if (i % primes[j] == 0) break;}}}int main(){int n;cin >> n;get_primes(n);cout << cnt << endl;return 0;}
约数
869. 试除法求约数
给定 n 个正整数 ai,对于每个整数 ai,请你按照从小到大的顺序输出它的所有约数。
输入格式
第一行包含整数 n。
接下来 n 行,每行包含一个整数 ai。
输出格式
输出共 n 行,其中第 i 行输出第 i 个整数 ai 的所有约数。
输入样例:
2
6
8
输出样例:
1 2 3 6
1 2 4 8
i 是x的约数,那么n/i也一定是x的约数,所以只要枚举到i<=n/i即可
#include <iostream>#include <cstring>#include <algorithm>#include <vector>using namespace std;vector<int> get_div(int x){vector<int>res;for (int i = 1; i <= x/i; i ++ ){if(x%i==0){res.push_back(i);if(x/i!=i){res.push_back(x/i);}}}sort(res.begin(),res.end());return res;}int main(){int n;cin >> n;for (int i = 0; i < n; i ++ ){int x;cin >> x;auto t = get_div(x);for(auto c:t){cout << c <<" ";}cout << endl;}}
870. 约数个数
给定 n 个正整数 ai,请你输出这些数的乘积的约数个数,答案对 109+7 取模。
输入格式
第一行包含整数 n。
接下来 n 行,每行包含一个整数 ai。
输出格式
输出一个整数,表示所给正整数的乘积的约数个数,答案需对 109+7 取模。
输入样例:
3
2
6
8
输出样例:
12
依次分解每一个数
#include <iostream>#include <cstring>#include <algorithm>#include <unordered_map>#define x first#define y secondusing namespace std;typedef long long LL;const int mod = 1e9+7;unordered_map<int,int>primes;void get_primes(int x){for (int i = 2; i <= x/i; i ++ ){while(x%i==0){primes[i]++;x/=i;}}if(x>1){primes[x]++;}}int main(){int n;cin >> n;while (n -- ){int x;cin >> x;get_primes(x);}LL res=1;for(auto s:primes){res = res * (s.y+1)%mod;}cout << res;}
871. 约数之和
给定 n 个正整数 ai,请你输出这些数的乘积的约数之和,答案对 109+7 取模。
输入格式
第一行包含整数 n。
接下来 n 行,每行包含一个整数 ai。
输出格式
输出一个整数,表示所给正整数的乘积的约数之和,答案需对 109+7 取模。
输入样例:
3
2
6
8
输出样例:
252
#include <iostream>#include <cstring>#include <algorithm>#include <unordered_map>#define x first#define y secondusing namespace std;typedef long long LL;const int mod = 1e9+7;unordered_map<int,int>primes;void get_primes(int x){for (int i = 2; i <= x/i; i ++ ){while(x%i==0){primes[i]++;x/=i;}}if(x>1){primes[x]++;}}int main(){int n;cin >> n ;for (int i = 0; i < n; i ++ ){int x;cin >> x;get_primes(x);}LL res=1;for(auto s:primes){int p = s.x;int cnt = s.y;LL sum=1;for (int i = 1; i <=cnt ; i ++ ){sum = (sum * p + 1)%mod;}res = (res * sum)%mod;}cout << res;}
博弈论
891. Nim游戏
给定 n 堆石子,两位玩家轮流操作,每次操作可以从任意一堆石子中拿走任意数量的石子(可以拿完,但不能不拿),最后无法进行操作的人视为失败。
问如果两人都采用最优策略,先手是否必胜。
输入格式
第一行包含整数 n。
第二行包含 n 个数字,其中第 i 个数字表示第 i 堆石子的数量。
输出格式
如果先手方必胜,则输出 Yes。
否则,输出 No。
数据范围
1≤n≤105,
1≤每堆石子数≤109
输入样例:
2
2 3
输出样例:
Yes
#include <iostream>#include <cstdio>using namespace std;/*先手必胜状态:先手操作完,可以走到某一个必败状态先手必败状态:先手操作完,走不到任何一个必败状态先手必败状态:a1 ^ a2 ^ a3 ^ ... ^an = 0先手必胜状态:a1 ^ a2 ^ a3 ^ ... ^an ≠ 0*/int main(){int n;scanf("%d", &n);int res = 0;for(int i = 0; i < n; i++) {int x;scanf("%d", &x);res ^= x;}if(res == 0) puts("No");else puts("Yes");}
矩阵乘法
1303. 斐波那契前 n 项和
大家都知道 Fibonacci 数列吧,f1=1,f2=1,f3=2,f4=3,…,fn=fn−1+fn−2。
现在问题很简单,输入 n 和 m,求 fn 的前 n 项和 Snmodm。
输入格式
共一行,包含两个整数 n 和 m。
输出格式
输出前 n 项和 Snmodm 的值。
数据范围
1≤n≤2000000000,
1≤m≤1000000010
输入样例:
5 1000
输出样例:
12
#include <iostream>#include <cstring>#include <algorithm>typedef long long LL;using namespace std;const int N = 3;LL n, m;void mul(LL c[][N], LL a[][N], LL b[][N]) {LL temp[N][N] = {0};for (int i = 0; i < N; i++) {for (int j = 0; j < N; j++) {for (int k = 0; k < N; k++) {temp[i][j] = (temp[i][j] + a[i][k] * b[k][j]) % m;}}}memcpy(c, temp, sizeof temp);}int main() {cin >> n >> m;if (n <= 2) {cout << n % m << endl;return 0;}LL f[N][N] = {{1, 1, 2}};n -= 2;LL w[N][N] = {{0, 1, 1},{1, 1, 1},{0, 0, 1},};while (n) {if (n & 1) {mul(f, f, w);};n >>= 1;mul(w, w, w);}cout << f[0][2] % m;}
1304. 佳佳的斐波那契
佳佳对数学,尤其对数列十分感兴趣。
在研究完 Fibonacci 数列后,他创造出许多稀奇古怪的数列。
例如用 S(n) 表示 Fibonacci 前 n 项和 modm 的值,即 S(n)=(F1+F2+…+Fn)modm,其中 F1=F2=1,Fi=Fi−1+Fi−2。
可这对佳佳来说还是小菜一碟。
终于,她找到了一个自己解决不了的问题。
用 T(n)=(F1+2F2+3F3+…+nFn)modm 表示 Fibonacci 数列前 n 项变形后的和 modm 的值。
现在佳佳告诉你了一个 n 和 m,请求出 T(n) 的值。
输入格式
共一行,包含两个整数 n 和 m。
输出格式
共一行,输出 T(n) 的值。
数据范围
1≤n,m≤231−1
输入样例:
5 5
输出样例:
1
样例解释
T(5)=(1+2×1+3×2+4×3+5×5)mod5=1
#include <iostream>#include <cstring>#include <algorithm>typedef long long LL;using namespace std;const int N = 4;LL n, m;void mul(LL c[][N], LL a[][N], LL b[][N]) {LL temp[N][N] = {0};for (int i = 0; i < N; i++) {for (int j = 0; j < N; j++) {for (int k = 0; k < N; k++) {temp[i][j] = (temp[i][j] + a[i][k] * b[k][j]) % m;}}}memcpy(c, temp, sizeof temp);}int main() {cin >> n >> m;if (n == 1) {cout << 1 % m << endl;return 0;}else if(n == 2){cout << 3 % m <<endl;return 0;}LL f[N][N] = {{1, 1, 2, 1}};LL w[N][N] = {{0, 1, 1, 0},{1, 1, 1, 0},{0, 0, 1, 1},{0, 0, 0, 1},};int k = n-2;while (k) {if (k & 1) {mul(f, f, w);};k >>= 1;mul(w, w, w);}cout << (n*f[0][2]%m+m-f[0][3]%m) % m;}
1305. GT考试
阿申准备报名参加 GT 考试,准考证号为 n 位数 X1X2⋯Xn,他不希望准考证号上出现不吉利的数字。
他的不吉利数字 A1A2⋯Am 有 m 位,不出现是指 X1X2⋯Xn 中没有恰好一段等于 A1A2⋯Am,A1 和 X1 可以为 0。
输入格式
第一行输入 n,m,K。
接下来一行输入 m 位的不吉利数字。
输出格式
阿申想知道不出现不吉利数字的号码有多少种,输出模 K 取余的结果。
输入样例:
4 3 100
111
输出样例:
81




// 常规解法#include <iostream>#include <cstring>#include <algorithm>using namespace std;const int M=25,N=1e5;int ne[M];string p;int n,m,K;int f[N][M];int main(){cin >> n >> m >> K;cin >> p ;p = " "+p;for (int i = 2,j = 0; i <= m; i ++ ){while(j&&p[i]!=p[j+1]){j = ne[j];}if(p[i]==p[j+1]){j++;}ne[i] = j;}f[0][0] = 1;for (int i = 0; i < n; i ++ ){ // 长度for (int j = 0; j < m; j ++ ){ // 当前走到模板串哪个位置上for (int k = 0; k <= 9; k ++ ){ // 当前的选择int u = j;while(u&&p[u+1]!=k+'0'){u = ne[u];}if(p[u+1]==k+'0'){u = u+1;}//f[i+1][u] = (f[i+1][u] + f[i][j])%K;f[(i+1)&1][u] = (f[(i+1)&1][u] + f[i&1][j])%K;}f[i&1][j]=0; // 要用滚动数组的话必须这里清零}}int res=0;for (int j = 0; j < m ; j ++ ){res = (res + f[n&1][j])%K;}cout << res;}
// 矩阵乘法#include <iostream>#include <cstring>#include <algorithm>using namespace std;int n,m,K;const int N = 25;int ne[N];int A[N][N];int f[N][N];string p;void mul(int c[][N],int a[][N],int b[][N]){int t[N][N];memset(t, 0, sizeof t);for (int i = 0; i < m; i ++ ){for (int j = 0; j < m; j ++ ){for (int k = 0; k < m; k ++ ){t[i][j] = (t[i][j] + a[i][k]*b[k][j])%K;}}}memcpy(c,t,sizeof t);}void qmi(){f[0][0]=1;while(n){if(n&1){mul(f,f,A);}n>>=1;mul(A,A,A);}int res=0;for (int i = 0; i < m; i ++ ){res = (res + f[0][i])%K;}cout << res;}int main(){cin >> n >> m >> K; // m是p串的长度cin >> p;p = " "+p;// 求ne数组for (int i = 2,j=0; i <= m; i ++ ){while(j&&p[i]!=p[j+1]){j = ne[j];}if(p[i]==p[j+1]){j++;}ne[i]=j;}// 求A矩阵for (int i = 0; i < m; i ++ ){for (int j = 0; j <= 9; j ++ ){int u = i;while(u&&p[u+1]!=j+'0'){u = ne[u];}if(p[u+1]==j+'0'){u++;}if(u<m){A[i][u]++;}}}//快速幂qmi();}
依次分解每一个数