題目傳送門
題意:
給你 個數 ,讓你挑兩個數,把這兩個數拼起來,例如 和 拼起來是 。
問拼起來的數是 的倍數的方案數。認爲 和 是不同的方案。都滿足 。
數據範圍: 。
題解:
我們挑選的其實是 。
位數比較小,可以預處理出來。
因此我們就枚舉 ,去尋找 。
後面的是可以預處理出來的。
感受:
這道題 和 都能做。
假如用 ,那得先 判定存在還是不存在。
如果不存在就去索引,那會慢很多。
代碼:
#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
const int maxn = 2e5 + 5 ;
int n , k , a[maxn] , num[maxn] ;
ll ten[maxn] ;
map<int , int> mp[15] ;
void init()
{
for(int i = 1 ; i <= n ; i ++)
{
int x = a[i] ;
while(x > 0) x /= 10 , num[i] ++ ;
if(mp[num[i]].count(a[i] % k)) mp[num[i]][a[i] % k] ++ ;
else mp[num[i]][a[i] % k] = 1 ;
}
ten[0] = 1 ;
for(int i = 1 ; i <= 10 ; i ++)
ten[i] = ten[i - 1] * 10 % k ;
}
bool ok(int i)
{
ll y = ll(a[i]) * ten[num[i]] % k ;
y += a[i] , y %= k ;
return y == 0 ;
}
int cal(int i , int j)
{
ll x = a[i] ;
int y ;
int ans = 0 ;
x = x * ten[j] % k ;
y = k - (int) x ;
y %= k ;
if(mp[j].count(y)) ans += mp[j][y] ;
return ans ;
}
void solve()
{
ll ans = 0 ;
for(int i = 1 ; i <= n ; i ++)
for(int j = 1 ; j <= 10 ; j ++)
ans += cal(i , j) ;
for(int i = 1 ; i <= n ; i ++)
if(ok(i)) ans -- ;
printf("%lld\n" , ans) ;
}
int main()
{
scanf("%d%d" , &n , &k) ;
for(int i = 1 ; i <= n ; i ++) scanf("%d" , &a[i]) ;
init() ;
solve() ;
return 0 ;
}