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

版权声明:如需转载,记得标识出处 https://blog.csdn.net/godleaf/article/details/82053397

题目链接: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;
}

猜你喜欢

转载自blog.csdn.net/godleaf/article/details/82053397