[蓝桥杯][2020年第十一届真题第一场]整数拼接

题目描述:

给定一个长度为 n 的数组 A1,A2,⋅⋅⋅,An。


你可以从中选出两个数 Ai 和 Aj(i 不等于 j),然后将 Ai 和 Aj 一前一后拼成一个新的整数。


例如 12 和 345 可以拼成 12345 或 34512。


注意交换 Ai 和 Aj 的顺序总是被视为 2 种拼法,即便是 Ai=Aj 时。


请你计算有多少种拼法满足拼出的整数是 K 的倍数。


输入格式 第一行包含 2 个整数 n 和 K。

第二行包含 n 个整数 A1,A2,⋅⋅⋅,An。


输出格式 一个整数代表答案。


数据范围 1≤n≤105, 1≤K≤105, 1≤Ai≤109

输入样例: 4 2 1 2 3 4
输出样例: 6

解题思路:

考虑如何快速求出与a[i]拼接起来为k的倍数的数字。

要与a[i]拼接起来是k的倍数,那首先要考虑a[i]和a[j]拼起来是个啥玩意。

观察到a[i]与a[j]拼起来的结果即为 a [ i ] × 10 ⌊ l o g 10 a [ j ] ⌋ + a [ j ] a [ i ] × 10 ⌊ l o g 10 ⁡ a [ j ] ⌋ + a [ j ] a[i]×10⌊log10a[j]⌋+a[j]a[i]×10⌊log10⁡a[j]⌋+a[j] a[i]×10log10a[j]+a[j]a[i]×10log10a[j]+a[j]

那要 a [ i ] × 10 ⌊ l o g 10 a [ j ] ⌋ + a [ j ] a [ i ] × 10 ⌊ l o g 10 ⁡ a [ j ] ⌋ + a [ j ] a[i]×10⌊log10a[j]⌋+a[j]a[i]×10⌊log10⁡a[j]⌋+a[j] a[i]×10log10a[j]+a[j]a[i]×10log10a[j]+a[j]是 k 的倍数,也就是要 a [ i ] × 10 ⌊ l o g 10 a [ j ] ⌋ % k + a [ j ] % k a [ i ] × 10 ⌊ l o g 10 ⁡ a [ j ] ⌋ % k + a [ j ] % k a[i]×10⌊log10a[j]⌋\%k+a[j]\%ka[i]×10⌊log10⁡a[j]⌋\%k+a[j]\%k a[i]×10log10a[j]%k+a[j]%ka[i]×10log10a[j]%k+a[j]%k 是 k 的倍数。

然后注意到 a [ i ] × 10 ⌊ l o g 10 a [ j ] ⌋ % k a [ i ] × 10 ⌊ l o g 10 ⁡ a [ j ] ⌋ % k a[i]×10⌊log10a[j]⌋\%ka[i]×10⌊log10⁡a[j]⌋\%k a[i]×10log10a[j]%ka[i]×10log10a[j]%k 这个数字是小于k的,而k最大是 1 0 5 10^{5} 105
也就是说,我们是可以将其储存起来的。

所以我们可以开一个cnt数组,其中cnt[i][j]记录在之前遍历过的所有数中,乘 1 0 i {10^i} 10i后模 m 的结果为 j 的数的个数。
然后对于所有的a[i],累加 c n t [ l o g 10 a [ i ] ] [ ( m − a [ i ] % m ) % m ] cnt[log10a[i]][(m−a[i]\%m)\%m] cnt[log10a[i]][(ma[i]%m)%m]即可。

但这只能求出所有 i<ji<j 的合法的 a[i] 与 a[j] 的个数。
从前往后跑一遍,从后往前再跑一遍就可以

#include<bits/stdc++.h>
#define x first
#define y second
#define mem-1(h) memset(h,-1,sizeof h)
#define mem0(h) memset(h,0,sizeof h)
#define mcp(a,b) memcpy(a,b,sizeof b)
using namespace std;
typedef long long LL;
typedef unsigned long long ull; 
typedef pair<int,int>PII;
typedef pair<double,double>PDD;
namespace IO{
    
	inline LL read(){
    
		LL o=0,f=1;char c=getchar();
		while(c<'0'||c>'9'){
    if(c=='-')f=-1;c=getchar();}
		while(c>='0'&&c<='9'){
    o=o*10+c-'0';c=getchar();}
		return o*f;
	}
}using namespace IO;
//#############以上是自定义技巧(可忽略)########## 
const int N=1e5+7,M=2e5+7,INF=0x3f3f3f3f,mod=1e8+7,P=131;
LL ans;
int a[N];
int cnt[12][N];
int n,k;
int log_10(int x){
    
	int res=0;
	while(x){
    
		x/=10;
		res++;
	}
	return res;
}
void solve(){
    
	for(int i=0;i<n;i++){
    
		ans+=cnt[log_10(a[i])][(k-a[i]%k)%k];
		for(int j=0,pow=1;j<11;j++){
    
			cnt[j][pow*1ll*a[i]%k]++;
			pow=pow*10%k;
		}
	}
}
int main(){
    
	cin>>n>>k;
	for(int i=0;i<n;i++)cin>>a[i];
	solve();
	mem0(cnt);
	reverse(a,a+n);
	solve();
	cout<<ans<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43738764/article/details/109034964