[Acwing] 第 67 场周赛

前言

t a g : tag : tag: 数学
传送门 :

题意 :
寻找满足 a i a j a_ia_j aiaj能被 k k k整除的数对数量

思路 :

我们可得公式 :

( a i ∗ T + a j ) % k = 0 (a_i*T + a_j)\%k=0 (aiT+aj)%k=0

a [ i ] ∗ T % k = x 1 a[i]*T\%k =x_1 a[i]T%k=x1
a [ j ] % k = x 2 a[j]\%k =x_2 a[j]%k=x2
x 1 + x 2 = k x_1+x_2=k x1+x2=k

形如 x 1 + x 2 = k x_1+x_2 =k x1+x2=k我们都可以用 m a p map map解决

不过这次带有一个 T T T

我们可以枚举 a i a_i ai当作尾数,因此我们需要预处理 a i a_i ai的位数

因为 a i < = 1 0 9 a_i<=10^9 ai<=109,因此我们开 m a p [ 11 ] map[11] map[11]进行存放答案

后面我们只需要枚举 a [ i ] ∗ T % k a[i]*T\%k a[i]T%k即可,当然需要注意特
判自己的情况

code :

map<ll,ll> mp[11];

const int N = 2e5+10,INF = 0x3f3f3f3f;
const double eps = 1e-5;


struct node{
    int to,val;
};


int n,k;
ll a[N];
int i,j;
ll cnt[N];
ll ans;

void solve(){
	cin>>n>>k;
	Fup(i,1,n){
		cin>>a[i];
		ll temp = a[i];
		if(temp == 0)  cnt[i] = 1;
		else{
			while(temp){
				++cnt[i];
				temp/=10;
			}
		}
		mp[cnt[i]][a[i]%k]++;
	}
	
	Fup(i,1,n){
		ll x = a[i];
		
		Fup(j,1,10){
			
			x = x*10%k;
			
			if(mp[j].find((k-x)%k)!= mp[j].end()){
				ans += mp[j][(k-x)%k];
				if(cnt[i] == j && a[i]%k == (k-x)%k) --ans;
			}
			
		}
	}
	cout<<ans<<endl;
	

}

int main(){
	IOS
	CIT
	COT
	//int t;cin>>t;while(t--)
    solve();
    return 0 ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值