藍橋杯 整數拼接

Edviv發表於2020-10-16

整數拼接
題目大意
給定一個長度為 n n n 的陣列 A 1 , A 2 , ⋅ ⋅ ⋅ , A n A_1,A_2,⋅⋅⋅,A_n A1,A2,,An
你可以從中選出兩個數 A i A_i Ai A j A_j Aj( i i i 不等於 j j j),然後將 A i A_i Ai A j A_j Aj 一前一後拼成一個新的整數。
例如 12 和 345 可以拼成 12345 或 34512。
注意交換 A i A_i Ai A j A_j Aj 的順序總是被視為 2 種拼法,即便是 A i = A j A_i=A_j Ai=Aj 時。
請你計算有多少種拼法滿足拼出的整數是 K K K 的倍數。
輸入格式
第一行包含 2 個整數 n n n K K K
第二行包含 n n n 個整數 A 1 , A 2 , ⋅ ⋅ ⋅ , A n A_1,A_2,⋅⋅⋅,A_n A1,A2,,An
輸出格式
一個整數代表答案。
資料範圍: 1 ≤ n ≤ 1 0 5 , 1 ≤ K ≤ 1 0 5 , 1 ≤ A i ≤ 1 0 9 1≤n≤10^5,1≤K≤10^5,1≤A_i≤10^9 1n105,1K105,1Ai109
輸入樣例

4 2
1 2 3 4

輸出樣例

6

暴力程式碼 O ( n 2 ) O(n^2) O(n2)

ll ans = 0;
ll num[11]={0,1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000};
for(int i = 0; i < n; i++)
    for(int j = 0; j < n; j++)
    {
        if(i!=j)
        {
            int leni = get_len(a[i]), lenj = get_len(a[j]);
            ll t = a[i]*num[lenj]+a[j];
            if(t%k==0) ans++;
            t = a[j]*num[leni]+a[i];
            if(t%k==0) ans++;
        }
    }

所謂的優化就是空間換時間,外層迴圈無法去掉,那麼我們就想辦法去掉內層迴圈的東西。
a [ i ] g e t l e n ( a [ j ] ) a[i]^{getlen(a[j])} a[i]getlen(a[j])+ a [ j ] a[j] a[j]

拆成兩部分 a[i]*10^(getlen(a[j])) 和 a[j]
(k-a[j]%k)%k  //放在後面符合拼接數的個數
for(int t = 1, j = 0; j <= 10; j++)
{
    cnt[j][a[i]*t%k]++;  //放在前面
    t = t*10%k;
}
j <= 10 是因為 get_len獲取的長度1e910,所以 j 要遍歷完二維維所有資料需要注意 j >= 10,但是也不能太大。然後翻轉陣列再求一次就是我們最終需要的結果
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 7;
ll a[maxn], n, k, ans = 0;
ll cnt[15][maxn];  //cnt[i][j]存乘以10^i%k餘數是j的數

int get_len(int x)  //獲取字元長度
{
    int res = 0;
    while(x)
    {
        res++;
        x /= 10;
    }
    return res;
}

void solve()
{
    memset(cnt, 0 ,sizeof cnt);  //清0
  
    for(int i = 0; i < n; i++)
    {
        ans += cnt[get_len(a[i])][(k - a[i]%k)%k]; //a[i]放在後面
        for(int t = 1,j = 0; j < 11; j++)
        {
            cnt[j][t*a[i]%k]++;  //a[i]放在前面
            t = t*10%k;
        }
    }
}

int main()
{
    scanf("%d%d",&n,&k);
    for(int i = 0; i < n; i++) scanf("%lld",&a[i]);
    solve();
    reverse(a,a+n);
    solve();
    printf("%lld\n",ans);
    return 0;
}

相關文章