进制转换

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

  1. #include <iostream>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. int n;
  6. int get(int x,int){
  7. if(x>=0&&x<=9){
  8. return x+'0';
  9. }else{
  10. return 'A'+x-10;
  11. }
  12. }
  13. string get(int x){
  14. string res="";
  15. if(x==0){ // 必须单独处理一下 0
  16. return "0";
  17. }
  18. while(x){
  19. res+=get(x%16,0);
  20. x/=16;
  21. }
  22. return res;
  23. }
  24. int cal(string s){
  25. int res=0;
  26. for (int i = 0; i < s.size(); i ++ ){
  27. if(s[i]=='0'||s[i]=='4'||s[i]=='6'||s[i]=='9'||s[i]=='A'||s[i]=='D'){
  28. res++;
  29. }else if(s[i]=='8'||s[i]=='B'){
  30. res+=2;
  31. }
  32. }
  33. return res;
  34. }
  35. int main()
  36. {
  37. cin >> n;
  38. string s = get(n);
  39. cout << cal(s);
  40. }

质数

866. 试除法判定质数

给定 n 个正整数 ai,判定每个数是否是质数。
输入格式
第一行包含整数 n
接下来 n 行,每行包含一个正整数 ai
输出格式
n 行,其中第 i 行输出第 i 个正整数 ai 是否为质数,是则输出 Yes,否则输出 No。
输入样例:
2 2 6
输出样例:
Yes No

  1. #include <iostream>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. bool is_prime(int n){
  6. if(n<2){
  7. return false;
  8. }
  9. for (int i = 2; i <= n/i; i ++ ){
  10. if(n%i==0){
  11. return false;
  12. }
  13. }
  14. return true;
  15. }
  16. int main(){
  17. int n;
  18. cin >> n;
  19. for (int i = 0; i < n; i ++ ){
  20. int x;
  21. cin >> x;
  22. if(is_prime(x)){
  23. cout << "Yes"<<endl;
  24. }else{
  25. cout << "No" <<endl;
  26. }
  27. }
  28. }

867. 分解质因数

给定 nn 个正整数 aiai,将每个数分解质因数,并按照质因数从小到大的顺序输出每个质因数的底数和指数。
输入格式
第一行包含整数 nn。
接下来 nn 行,每行包含一个正整数 aiai。
输出格式
对于每个正整数 aiai,按照从小到大的顺序输出其分解质因数后,每个质因数的底数和指数,每个底数和指数占一行。
每个正整数的质因数全部输出完毕后,输出一个空行。
输入样例:
2 6 8
输出样例:

2 1 3 1

2 3

image.png

  1. #include <iostream>
  2. #include <algorithm>
  3. using namespace std;
  4. void divide(int x)
  5. {
  6. for (int i = 2; i <= x / i; i ++ )
  7. if (x % i == 0)
  8. {
  9. int s = 0;
  10. while (x % i == 0) x /= i, s ++ ;
  11. cout << i << ' ' << s << endl;
  12. }
  13. if (x > 1) cout << x << ' ' << 1 << endl;
  14. cout << endl;
  15. }
  16. int main()
  17. {
  18. int n;
  19. cin >> n;
  20. while (n -- )
  21. {
  22. int x;
  23. cin >> x;
  24. divide(x);
  25. }
  26. return 0;
  27. }

868. 筛质数

给定一个正整数 n,请你求出 1∼n 中质数的个数。
输入格式
共一行,包含整数 n。
输出格式
共一行,包含一个整数,表示 1∼n 中质数的个数。
输入样例:
8
输出样例:
4

  1. #include <iostream>
  2. #include <algorithm>
  3. using namespace std;
  4. const int N= 1000010;
  5. int primes[N], cnt;
  6. bool st[N];
  7. void get_primes(int n)
  8. {
  9. for (int i = 2; i <= n; i ++ )
  10. {
  11. if (!st[i]) primes[cnt ++ ] = i;
  12. for (int j = 0; primes[j] <= n / i; j ++ )
  13. {
  14. st[primes[j] * i] = true;
  15. if (i % primes[j] == 0) break;
  16. }
  17. }
  18. }
  19. int main()
  20. {
  21. int n;
  22. cin >> n;
  23. get_primes(n);
  24. cout << cnt << endl;
  25. return 0;
  26. }

约数

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即可

  1. #include <iostream>
  2. #include <cstring>
  3. #include <algorithm>
  4. #include <vector>
  5. using namespace std;
  6. vector<int> get_div(int x){
  7. vector<int>res;
  8. for (int i = 1; i <= x/i; i ++ ){
  9. if(x%i==0){
  10. res.push_back(i);
  11. if(x/i!=i){
  12. res.push_back(x/i);
  13. }
  14. }
  15. }
  16. sort(res.begin(),res.end());
  17. return res;
  18. }
  19. int main()
  20. {
  21. int n;
  22. cin >> n;
  23. for (int i = 0; i < n; i ++ ){
  24. int x;
  25. cin >> x;
  26. auto t = get_div(x);
  27. for(auto c:t){
  28. cout << c <<" ";
  29. }
  30. cout << endl;
  31. }
  32. }

image.png

870. 约数个数

给定 n 个正整数 ai,请你输出这些数的乘积的约数个数,答案对 109+7 取模。
输入格式
第一行包含整数 n。
接下来 n 行,每行包含一个整数 ai。
输出格式
输出一个整数,表示所给正整数的乘积的约数个数,答案需对 109+7 取模。
输入样例:
3
2
6
8
输出样例:
12

image.png 依次分解每一个数

  1. #include <iostream>
  2. #include <cstring>
  3. #include <algorithm>
  4. #include <unordered_map>
  5. #define x first
  6. #define y second
  7. using namespace std;
  8. typedef long long LL;
  9. const int mod = 1e9+7;
  10. unordered_map<int,int>primes;
  11. void get_primes(int x){
  12. for (int i = 2; i <= x/i; i ++ ){
  13. while(x%i==0){
  14. primes[i]++;
  15. x/=i;
  16. }
  17. }
  18. if(x>1){
  19. primes[x]++;
  20. }
  21. }
  22. int main()
  23. {
  24. int n;
  25. cin >> n;
  26. while (n -- ){
  27. int x;
  28. cin >> x;
  29. get_primes(x);
  30. }
  31. LL res=1;
  32. for(auto s:primes){
  33. res = res * (s.y+1)%mod;
  34. }
  35. cout << res;
  36. }

871. 约数之和

给定 n 个正整数 ai,请你输出这些数的乘积的约数之和,答案对 109+7 取模。
输入格式
第一行包含整数 n。
接下来 n 行,每行包含一个整数 ai。
输出格式
输出一个整数,表示所给正整数的乘积的约数之和,答案需对 109+7 取模。
输入样例:
3
2
6
8
输出样例:
252
image.png

  1. #include <iostream>
  2. #include <cstring>
  3. #include <algorithm>
  4. #include <unordered_map>
  5. #define x first
  6. #define y second
  7. using namespace std;
  8. typedef long long LL;
  9. const int mod = 1e9+7;
  10. unordered_map<int,int>primes;
  11. void get_primes(int x){
  12. for (int i = 2; i <= x/i; i ++ ){
  13. while(x%i==0){
  14. primes[i]++;
  15. x/=i;
  16. }
  17. }
  18. if(x>1){
  19. primes[x]++;
  20. }
  21. }
  22. int main()
  23. {
  24. int n;
  25. cin >> n ;
  26. for (int i = 0; i < n; i ++ ){
  27. int x;
  28. cin >> x;
  29. get_primes(x);
  30. }
  31. LL res=1;
  32. for(auto s:primes){
  33. int p = s.x;
  34. int cnt = s.y;
  35. LL sum=1;
  36. for (int i = 1; i <=cnt ; i ++ ){
  37. sum = (sum * p + 1)%mod;
  38. }
  39. res = (res * sum)%mod;
  40. }
  41. cout << res;
  42. }

博弈论

891. Nim游戏

给定 n 堆石子,两位玩家轮流操作,每次操作可以从任意一堆石子中拿走任意数量的石子(可以拿完,但不能不拿),最后无法进行操作的人视为失败。
问如果两人都采用最优策略,先手是否必胜。
输入格式
第一行包含整数 n。
第二行包含 n 个数字,其中第 i 个数字表示第 i 堆石子的数量。
输出格式
如果先手方必胜,则输出 Yes。
否则,输出 No。
数据范围
1≤n≤105,
1≤每堆石子数≤109
输入样例:
2
2 3
输出样例:
Yes
image.png

  1. #include <iostream>
  2. #include <cstdio>
  3. using namespace std;
  4. /*
  5. 先手必胜状态:先手操作完,可以走到某一个必败状态
  6. 先手必败状态:先手操作完,走不到任何一个必败状态
  7. 先手必败状态:a1 ^ a2 ^ a3 ^ ... ^an = 0
  8. 先手必胜状态:a1 ^ a2 ^ a3 ^ ... ^an ≠ 0
  9. */
  10. int main(){
  11. int n;
  12. scanf("%d", &n);
  13. int res = 0;
  14. for(int i = 0; i < n; i++) {
  15. int x;
  16. scanf("%d", &x);
  17. res ^= x;
  18. }
  19. if(res == 0) puts("No");
  20. else puts("Yes");
  21. }

矩阵乘法

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

  1. #include <iostream>
  2. #include <cstring>
  3. #include <algorithm>
  4. typedef long long LL;
  5. using namespace std;
  6. const int N = 3;
  7. LL n, m;
  8. void mul(LL c[][N], LL a[][N], LL b[][N]) {
  9. LL temp[N][N] = {0};
  10. for (int i = 0; i < N; i++) {
  11. for (int j = 0; j < N; j++) {
  12. for (int k = 0; k < N; k++) {
  13. temp[i][j] = (temp[i][j] + a[i][k] * b[k][j]) % m;
  14. }
  15. }
  16. }
  17. memcpy(c, temp, sizeof temp);
  18. }
  19. int main() {
  20. cin >> n >> m;
  21. if (n <= 2) {
  22. cout << n % m << endl;
  23. return 0;
  24. }
  25. LL f[N][N] = {{1, 1, 2}};
  26. n -= 2;
  27. LL w[N][N] = {
  28. {0, 1, 1},
  29. {1, 1, 1},
  30. {0, 0, 1},
  31. };
  32. while (n) {
  33. if (n & 1) {
  34. mul(f, f, w);
  35. };
  36. n >>= 1;
  37. mul(w, w, w);
  38. }
  39. cout << f[0][2] % m;
  40. }

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

  1. #include <iostream>
  2. #include <cstring>
  3. #include <algorithm>
  4. typedef long long LL;
  5. using namespace std;
  6. const int N = 4;
  7. LL n, m;
  8. void mul(LL c[][N], LL a[][N], LL b[][N]) {
  9. LL temp[N][N] = {0};
  10. for (int i = 0; i < N; i++) {
  11. for (int j = 0; j < N; j++) {
  12. for (int k = 0; k < N; k++) {
  13. temp[i][j] = (temp[i][j] + a[i][k] * b[k][j]) % m;
  14. }
  15. }
  16. }
  17. memcpy(c, temp, sizeof temp);
  18. }
  19. int main() {
  20. cin >> n >> m;
  21. if (n == 1) {
  22. cout << 1 % m << endl;
  23. return 0;
  24. }else if(n == 2){
  25. cout << 3 % m <<endl;
  26. return 0;
  27. }
  28. LL f[N][N] = {{1, 1, 2, 1}};
  29. LL w[N][N] = {
  30. {0, 1, 1, 0},
  31. {1, 1, 1, 0},
  32. {0, 0, 1, 1},
  33. {0, 0, 0, 1},
  34. };
  35. int k = n-2;
  36. while (k) {
  37. if (k & 1) {
  38. mul(f, f, w);
  39. };
  40. k >>= 1;
  41. mul(w, w, w);
  42. }
  43. cout << (n*f[0][2]%m+m-f[0][3]%m) % m;
  44. }

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
image.png
image.png
image.png
image.png
image.png

  1. // 常规解法
  2. #include <iostream>
  3. #include <cstring>
  4. #include <algorithm>
  5. using namespace std;
  6. const int M=25,N=1e5;
  7. int ne[M];
  8. string p;
  9. int n,m,K;
  10. int f[N][M];
  11. int main()
  12. {
  13. cin >> n >> m >> K;
  14. cin >> p ;
  15. p = " "+p;
  16. for (int i = 2,j = 0; i <= m; i ++ ){
  17. while(j&&p[i]!=p[j+1]){
  18. j = ne[j];
  19. }
  20. if(p[i]==p[j+1]){
  21. j++;
  22. }
  23. ne[i] = j;
  24. }
  25. f[0][0] = 1;
  26. for (int i = 0; i < n; i ++ ){ // 长度
  27. for (int j = 0; j < m; j ++ ){ // 当前走到模板串哪个位置上
  28. for (int k = 0; k <= 9; k ++ ){ // 当前的选择
  29. int u = j;
  30. while(u&&p[u+1]!=k+'0'){
  31. u = ne[u];
  32. }
  33. if(p[u+1]==k+'0'){
  34. u = u+1;
  35. }
  36. //f[i+1][u] = (f[i+1][u] + f[i][j])%K;
  37. f[(i+1)&1][u] = (f[(i+1)&1][u] + f[i&1][j])%K;
  38. }
  39. f[i&1][j]=0; // 要用滚动数组的话必须这里清零
  40. }
  41. }
  42. int res=0;
  43. for (int j = 0; j < m ; j ++ ){
  44. res = (res + f[n&1][j])%K;
  45. }
  46. cout << res;
  47. }
  1. // 矩阵乘法
  2. #include <iostream>
  3. #include <cstring>
  4. #include <algorithm>
  5. using namespace std;
  6. int n,m,K;
  7. const int N = 25;
  8. int ne[N];
  9. int A[N][N];
  10. int f[N][N];
  11. string p;
  12. void mul(int c[][N],int a[][N],int b[][N]){
  13. int t[N][N];
  14. memset(t, 0, sizeof t);
  15. for (int i = 0; i < m; i ++ ){
  16. for (int j = 0; j < m; j ++ ){
  17. for (int k = 0; k < m; k ++ ){
  18. t[i][j] = (t[i][j] + a[i][k]*b[k][j])%K;
  19. }
  20. }
  21. }
  22. memcpy(c,t,sizeof t);
  23. }
  24. void qmi(){
  25. f[0][0]=1;
  26. while(n){
  27. if(n&1){
  28. mul(f,f,A);
  29. }
  30. n>>=1;
  31. mul(A,A,A);
  32. }
  33. int res=0;
  34. for (int i = 0; i < m; i ++ ){
  35. res = (res + f[0][i])%K;
  36. }
  37. cout << res;
  38. }
  39. int main()
  40. {
  41. cin >> n >> m >> K; // m是p串的长度
  42. cin >> p;
  43. p = " "+p;
  44. // 求ne数组
  45. for (int i = 2,j=0; i <= m; i ++ ){
  46. while(j&&p[i]!=p[j+1]){
  47. j = ne[j];
  48. }
  49. if(p[i]==p[j+1]){
  50. j++;
  51. }
  52. ne[i]=j;
  53. }
  54. // 求A矩阵
  55. for (int i = 0; i < m; i ++ ){
  56. for (int j = 0; j <= 9; j ++ ){
  57. int u = i;
  58. while(u&&p[u+1]!=j+'0'){
  59. u = ne[u];
  60. }
  61. if(p[u+1]==j+'0'){
  62. u++;
  63. }
  64. if(u<m){
  65. A[i][u]++;
  66. }
  67. }
  68. }
  69. //快速幂
  70. qmi();
  71. }