Codeforces Round #506 (Div. 3) D 【枚举+数学取模】

博客给出题目链接 http://codeforces.com/contest/1029/problem/D ,介绍解题思路。将数字拆成 (x*pow(10,i) + y) mod k == 0 形式,用 map 存储位数为 x 对应的 mod k 的个数,通过 (k - x*pow(10,i)mod k) 找对应 y mod k 存储结果,关键是(k-x*pow(10,i)mod k)mod k == y mod k。

题目链接:http://codeforces.com/contest/1029/problem/D

思路:

把数字拆成  (x*pow(10,i) + y) mod k == 0 ,用map存储位数为x对应的mod k的个数;用 (k - x*pow(10,i)mod k) 去找对应的 y mod k 存储的结果,速度更快;关键:(k-x*pow(10,i)mod k)mod k == y mod k

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<sstream>
#include<vector>
#include<string>
#include<set>

using namespace std;

#define IOS ios::sync_with_stdio(false); cin.tie(0);

int read(){

    int r=0,f=1;char p=getchar();
    while(p>'9'||p<'0'){if(p=='-')f=-1;p=getchar();}
    while(p>='0'&&p<='9'){r=r*10+p-48;p=getchar();}return r*f;
}

typedef long long ll;
typedef unsigned long long ull;
const int Maxn = 2e5+10;
const long long LINF = 1e18;
const int INF = 0x3f3f3f3f;
const int Mod = 10001;

ll a[Maxn],p[12];
int w[Maxn];
map<int,ll> mp[11];

int main (void)
{
    ll n,k,tmp = 10;
    scanf("%lld %lld",&n,&k);
    p[0] = 1;
    for (int i = 1; i < 11; ++i)  p[i] = p[i-1]*10%k; //注意数字溢出,分段取模
    for (ll i = 0; i < n; ++i) {
            scanf("%lld",&tmp);
            a[i] = tmp;
            while (tmp) { tmp/=10; w[i]++; }
            mp[w[i]][a[i]%k]++;  // mp左值为数的位数,右值为这个数mod k的结果
    }
    ll ans = 0;
    for (int i = 0; i < n; ++i) {
        mp[w[i]][a[i]%k]--;  // 计算和a[i]构成的数能整除k的个数,优先把自己删去,计算计算后再加回来
        for (int j = 1; j <= 10; ++j) {
            tmp = (k-(a[i]%k*p[j])%k)%k;  //  (k-a[i]*p[i])%k,不是k - (a[i]*p[i])%k;
            if(mp[j].count(tmp))            
            ans+=mp[j][tmp];  //如果不是整除关系,k-tmp可能为k的倍数
        }
        mp[w[i]][a[i]%k]++;
    }
    printf("%lld\n",ans);
    return 0;
}

 

 

### Codeforces Round 1013 Div. 3 部分题目解析 #### A. Good Numbers 此题的核心在于统计输入数据中特定数字的频率并验证其是否满足条件。具体实现方法如下: 程序通过 `map` 数据结构存储每个数字出现的次数,并逐一检查这些计数值是否达到指定的要求。 ```cpp void solve() { int n, m, k; cin >> n; map<int, int> mp; vector<int> a(n + 1); for (int i = 1; i <= n; i++) { cin >> a[i]; } for (int i = 1; i <= n; i++) { mp[a[i]]++; if (mp[2] >= 2 && mp[0] >= 3 && mp[1] >= 1 && mp[3] >= 1 && mp[5] >= 1) { cout << i << endl; return; } } cout << 0 << endl; } ``` 上述代码逻辑清晰地展示了如何利用哈希表来解决该问题[^1]。 --- #### B. Team Training 对于本题,目标是从给定字符串中删除某些字符以形成子串 `"2020"`。解决方案采用枚举的方式尝试不同的分割位置组合,从而快速判断是否存在合法方案。 以下是完整的 C++ 实现代码片段: ```cpp #include <bits/stdc++.h> using namespace std; #define int long long #define endl &#39;\n&#39; void solve() { int n; string a; cin >> n >> a; for (int i = 0; i <= 4; i++) { if (a.substr(0, i) + a.substr(n - (4 - i), 4 - i) == "2020") { puts("YES"); return; } } puts("NO"); } signed main() { int _ = 1; cin >> _; while (_--) solve(); } ``` 这段代码实现了对所有可能情况的有效覆盖,并提供了高效的解答方式。 --- #### 更多题目概述 虽然未提供其他题目的详细描述,但可以根据比赛惯例推测其余部分涉及的内容范围广泛,涵盖了动态规划、贪心算法以及图论等领域知识点。有兴趣者可访问官方平台获完整版题解资料[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值