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