第十四节 数论 - 1

$$建议阅读$$

AT_arc149_a 题解

洛谷链接&Atcoder 链接

本篇题解为此题较简单做法较少码量,并且码风优良,请放心阅读。

题目简述

求满足以下条件的小于 \(10 ^ n\) 数最大是多少?

  • 每一位数字均相同;

  • \(m\) 的倍数。

数据范围:\(1\le n\le 10^5\)\(1\le m\le 10^9\)

思路

首先每位数字都相同很好满足,仅需枚举 \(n\) 位后,枚举每位的数字 \(1 \sim 9\),注意不包含 \(0\),因为最高位不能\(0\)

接着想要满足是 \(m\) 的倍数,可以想到类似动态转移的思路,定义二维数组 \(mp[i][j]\) 表示在有 \(i\) 位数的情况下每位都为 \(j\) 的数除以 \(M\)余数。在枚举中实时更新答案,因为位数是从 \(1 \sim N\),每位是从 \(1 \sim 9\),所以存储的答案一定为最大的解

代码实现

经过以上分析及一些数组设计,很容易即可得到代码。首先我们先看一下 \(mp\) 数组的处理

for(int i = 1; i <= n; i ++)
	for(int j = 1; j <= 9; j ++) {
		mp[i][j] = (mp[i - 1][j] * 10 + j) % m;
		if(!mp[i][j]) ans1 = i, ans2 = j;
	}

可以看到第三行对于 \(mp\) 数组状态的转移

\[mp_{i,j} \gets mp_{i-1,j} \]

可以从 \(i-1\) 位都是 \(j\) 的余数转移过来,根据同余的相关知识很容易推出转移方程式

\[mp_{i,j} \gets (mp_{i-1,j} \times 10 + j) \% M \]

解决状态转移后需更新答案,这一部分很简单就不在赘述。接着需要在处理 \(mp\) 数组后,特判 \(-1\) 的情况:

if(!ans1 || !ans2) {
	cout << "-1\n";
	return 0;
}

这样整体代码框架就完成了。

AC code

#include<iostream>
using namespace std;

long long n, m, mp[100005][15];
long long ans1, ans2;

int main() {
	cin >> n >> m;
	for(int i = 1; i <= n; i ++)
		for(int j = 1; j <= 9; j ++) {
			mp[i][j] = (mp[i - 1][j] * 10 + j) % m;
			if(!mp[i][j]) ans1 = i, ans2 = j;
		}
	if(!ans1 || !ans2) {
		cout << "-1\n";
		return 0;
	}
	for(int i = 1; i <= ans1; i ++) cout << ans2;
	return 0;
}

提交记录

\[\text{The End!} \]

A. 优美子数列

题目描述

数学家小 \(Q\) 得到了一个长度为 \(n\) 的数列 {\(a_n\)}。

\(Q\) 的幸运数字是 \(k\),所以他认为,若一个子数列 \(a_l\), \(a_l + 1\), …, \(a_r\) 的和为 \(k\) 的倍数,则该子数列是优美子数列。

\(Q\) 现在想考考你,{\(a_n\)} 里有多少个优美子数列呢?

输入格式

第一行输入两个正整数 \(n,k\)

接下来一行输入 \(n\) 个数,代表 \(a_1\)\(a_n\)

输出格式

输出一行一个正整数,表示优美子数列的个数。

样例输入

5 3
1 2 3 4 5

样例输出

7

数据规模

对于 \(60\%\) 的数据,\(n \le 1000\)

对于 \(100\%\) 的数据,\(1 \le n \le 2 \times 10^5\)\(1 \le k \le 10^7\)\(-10^9 \le a_i \le 10^9\)

点击查看代码
#include<iostream>
#include<map>
using namespace std;

long long n, k, a[200005];
long long ans = 0;
map<long long, long long> mp;

int main() {
    cin >> n >> k;
    mp[0] ++;
    for(int i = 1; i <= n; i ++) {
        int x;
        cin >> x;
        x %= k;
        a[i] = ((a[i - 1] + x) % k + k) % k; // 防止负数
        ans += mp[a[i]];
        mp[a[i]] ++;
    }
    cout << ans << endl;
    return 0;
}
编译结果
compiled successfully
time: 309ms, memory: 11632kb, score: 100, status: Accepted
> test 1: time: 0ms, memory: 3492kb, points: 10, status: Accepted
> test 2: time: 0ms, memory: 3384kb, points: 10, status: Accepted
> test 3: time: 1ms, memory: 3408kb, points: 10, status: Accepted
> test 4: time: 0ms, memory: 3360kb, points: 10, status: Accepted
> test 5: time: 1ms, memory: 3376kb, points: 10, status: Accepted
> test 6: time: 0ms, memory: 3464kb, points: 10, status: Accepted
> test 7: time: 14ms, memory: 4752kb, points: 10, status: Accepted
> test 8: time: 174ms, memory: 11632kb, points: 10, status: Accepted
> test 9: time: 49ms, memory: 7076kb, points: 10, status: Accepted
> test 10: time: 70ms, memory: 4912kb, points: 10, status: Accepted
posted @ 2023-07-25 09:14  So_noSlack  阅读(123)  评论(0编辑  收藏  举报