1 条题解

  • 2
    @ 2025-10-25 9:42:46

    看到题目的第一眼,这不模拟吗?看到数据范围,特别是 nn ,幻想破灭。

    正解

    别看 nn 这么大,别着急,细心的你肯定发现,进行 22 次变异操作后,你会发现数字一定在 2×1062 \times 10^6 之中,所以你会发现,经过 2×106+12 \times 10^6 + 1 次就必然会有重复数字,所以我们把循环节提取出来,用剩余变异次数 %= 循环节长度,再进行 ‘剩余变异次数’ 次遍历。 时间复杂度 O(m)

    代码

    
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    int n = 0, m, f[2000010], c[11], cnt;
    // f[i] 记录 i 在之前枚举中有没有出现,如果有,出现在那里
    ll k;
    char s[100010];
    
    int main() {
        //freopen("data10.in", "r", stdin);
        //freopen("data10.out", "w", stdout);
    	scanf("%s%d%lld", s + 1, &m, &k);
    	int len = strlen(s + 1);
    	n = m;
    	for (int i = 1; i <= len; i++)
    		n += s[i] - '0';
    	// 高精度处理,并进行一次变异。
    	k--;
    	f[n] = 1;
    	memset(f, 0, sizeof(f));
    	for (int i = 2; ; i++) {
    		cnt = 0;
    		int t = n;
    		while (t) {
    			c[++cnt] = t % 10;
    			t /= 10;
    		}
    		n = m;
    		for (int i = 1; i <= cnt; i++)
    			n += c[i];
    		// 进行一次变异
    		k--;
    		if (f[n]) {
    			k %= i - f[n];
    			// 找到循环节,循环节长度 = 当前 - 上一次,即 i - f[n]
    			break;
    		} else
    			f[n] = i; // 处理 f
    	}
    	for (int i = 1; i <= k; i++) { // 进行 k 次遍历
    		cnt = 0;
    		int t = n;
    		while (t) {
    			c[++cnt] = t % 10;
    			t /= 10;
    		}
    		n = m;
    		for (int i = 1; i <= cnt; i++)
    			n += c[i];
    	}
    	printf("%d\n", n);
    }
    
    
    
    • 1

    信息

    ID
    1680
    时间
    1000ms
    内存
    256MiB
    难度
    9
    标签
    (无)
    递交数
    9
    已通过
    5
    上传者