题目:
蓝桥杯2020年第十一届省赛真题-整数拼接 – C语言网 (dotcpp.com)
根据题意,计算两个整数拼在一起能被K整除的个数;
思路:
通过二维数组
a[位数][余数]
,求出每个数作为左边的数%k 得到 的余数(0~k-1)的个数,接着在遍历每个数,通过
每个数的位数
,找到 加起来 正好 能整除k的数 的
个数
。
0.通过数组s将每个数字记录下来;
1. 数字位数是1~9位,设可能拼在右边的数的位数为 j 。
因为每个数都可能做 左边的数 ,因此需要
求 每个数 作为 左边的数 的时候被 k 取余
的情况;
设
result=(long long) pow (10 , j) * s[ i ]% k;
可以通过二维数组s[ j ][ result ]来记录,
注意result范围为(0 ~ k-1)
2. 每个数都可以作为右边的数,设数位为w。
当
(右边的数%k+左边的数*pow(10,w) )%k==0
时,这个数便可以
计入
。
将这个公式变形一下,可得
k-右边的数%k =
pow(10,w)* 左边的数 %k
。
设 flag = k – 右边的数 % k ;
注意特判:
如果 flag ==k 时,flag == 0 。这样
k-右边的数%k
范围为(0~ k-1)
通过ans=ans+a[ w ][ flag ] 计算总数;
注意特判:
如果 同一个数 作为 左边的数 + 作为 右边的数 可以整除K,那么ans–;
代码如下:
#include<bits/stdc++.h>
using namespace std;
long long a[11][100004];
long long s[100004];
int wei(long long n){
int ans=0;
while(n){
ans++;
n=n/10;
}
return ans;
}
signed main()
{
int n,k;
cin>>n>>k;
for (int i=0;i<n;i++){
cin>>s[i];
}
for(int j=1;j<10;j++){
for(int i=0;i<n;i++){
long long result=(long long)pow(10,j)*s[i]%k;
a[j][result%k]++;//0~k-1
}
}
long long ans=0;
for(int i=0;i<n;i++){
long long w=wei(s[i]);
int flag=k-s[i]%k;
if(flag==k)flag=0;
ans=ans+a[w][flag];
if((s[i]*(long long)pow(10,w)%k+s[i]%k)%k==0)ans--;
}
cout<<ans;
return 0;
}
PS:左边的数 求 余数 时也可以通过
( result -1 ) %k +1
来求余数,其范围是1~k。这样求右边的数的余数时就不需要特判了;