蓝桥杯2020年第十一届省赛真题-整数拼接

  • Post author:
  • Post category:其他


题目:

蓝桥杯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。这样求右边的数的余数时就不需要特判了;



版权声明:本文为zy98zy998原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。