VJ的MNNUrank的E

题意:

  给定数组A[] , 问两两数合并,有多少个合并数能被K整除。

思路:

  情况① :  a与b都可以整除k,他们的两个合并数必定都可以整除k

    打个比方 a = 36 , b = 12 , k = 6 

    由于 (a % k == 0 && b % k == 0) , 可得 (a + b) % k == 0 且 (b + a) % k == 0 , 也就是3612 % 6 = 0 , 1236 % 6 = 0

  情况② :排除情况①的其余情况,根据余数进行判定

    首先,假设 a 和 b 进行合并 , a 有 n 位 ,b 有 m 位 :

    假如合并方法是 a + b :那么实际上拼凑成的数是 a  * 10 ^ m + b ,那么判断这个数是否整除k,也就是判断(a  * 10 ^ m + b) % k == 0 ,

    也就是判断(a  * 10 ^ m + b)% k + b % k == 0 ?

    由于情况①以及排除了 (a % k == 0 && b % k == 0) 的情况 , 所以只能当 (a  * 10 ^ m + b)% k + b % k = k 时,情况才成立。

    由于ai数据最大的是1e9 , n , m <= 9  , 所以我们可以直接计算出 (a * 10 ^ i)% k (i = 0 , 1 , 2 , 3 ....,9)的情况并记录下来.

    然后对于位数为m , 模k后的值为temp的数 ,他作为尾巴(后置位)的对答案的贡献是:

      个数 (位数为m,乘10 ^ 0 , 模k后的值为temp)  *  个数(位数为1 ~ 9 ,乘10 ^ m , 模k后的值为 k - temp)

    由此计算出所有的答案

代码:

#include<bits/stdc++.h>

using namespace std;
const int maxn =  1e5 + 10;
#define ios std::ios::sync_with_stdio(false)

int a[maxn][10];///(b[i] * 10^j) % k
int b[maxn];///存数组
int num[maxn];///每个数有几位
int ma[10][10][maxn];///位数为i ,乘的数为10^j的,余数为k的,个数
signed main()
{
    ios;cin.tie(0);
    int n , k;
    cin >> n >> k;
    for(int i = 1 ; i <= n ; i ++){
        cin >> b[i];
        a[i][0] = b[i] % k;
        for(int j = 1 ; j <= 9 ; j ++){ ///计算*1 *10 *100 ... 后的模数
            a[i][j] = a[i][j - 1] * 10;
            a[i][j] %= k;
        }
    }
    for(int i = 1 ; i <= n ; i ++){ ///计算位数
        int cnt = 0;
        int now = b[i];
        while(now){
            cnt ++ , now /= 10;
        }
        num[i] = cnt;
    }

    for(int i = 1 ; i <= n ; i ++){
        for(int j = 0 ; j <= 9 ; j ++){
            ma[num[i]][j][a[i][j]] ++;///每个数的位数,乘10 ^ j , 模值为a[i][j]
        }
    }

    int ans = 0;
    for(int i = 1 ; i < 10 ; i ++){
        for(int j = 0 ; j < 10 ; j ++){
                for(int l = 1 ; l < k ; l ++) ans += ma[i][0][l] * ma[j][i][k - l];///情况2 ,(位数为i,模数为l的作为尾巴)(位数为j,乘10 ^ i,模数为k - l作为头)
        }
        if(ma[i][0][0] == 0)continue;
        int sum = 0;
        for(int l = 0 ; l < 10 ; l ++) sum += ma[l][i][0]; ///情况1
        ans += ma[i][0][0] * (sum - 1);///要排除掉自己和自己组合的那种
    }
    cout << ans << '\n';
    return 0;
}
View Code

 

    

 

  

  

posted @ 2020-09-24 20:25  GoodVv  阅读(303)  评论(0编辑  收藏  举报