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

#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;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值