Wannafly挑战赛29 B 白井黑子 (数论+map)

链接:https://ac.nowcoder.com/acm/contest/271/B
来源:牛客网
 

kuroko 作为常盘台唯一的空间系能力者,在每年例行的能力测试中可绝对不能让 misaka 失望哦,但是由于她的等级只是 level 4「大能力者」,在能力测试中会遇到不少困难。kuroko 是一个凡事都会尽力的好女孩,所以请你帮她算出她最多能完成多少测试吧

对于空间系能力者测试的内容是检验对物体进行空间移动的能力,测验时一共有 n 个物品放在一条直线上,每个物品都有一个坐标 ai ,kuroko 可以选择两个物品并使用能力交换它们的位置,但是如果两个物品的坐标不满足 kuroko 的计算公式的话,她就没有办法使用能力。

具体来说,对于坐标 ai ,其在 kuroko 的计算公式中是用参数 f(ai) 表示的。f(ai) 是 ai 各数位相乘的结果,由于 level 4「大能力者」在学园都市中也是很强大的存在,所以满足公式的条件不会太苛刻,对于两个物品 ai, aj ,如果 f(ai) x f(aj) 不能被某个自然数的 k 次幂表示 的话,那么 kuroko 就能对这两个物品使用能力。

现在 kuroko 想知道,有多少对物品她可以对其施展能力,知道了这个后她就知道自己能完成多少测验了。

这里认为任何自然数的 0 次幂都是 1。

输入描述:

第一行两个数,n, k 。

第二行共 n 个数 ai 表示这 n 个物品在直线上的坐标。

输出描述:

输出共一个数,表示 kuroko 能对其使用能力的无序物品对数。

示例1

输入

复制

6 3
113 10 11 1110 33 110

输出

复制

2

备注:

2 ≤ n ≤ 105, 0 ≤ ai, k ≤ 1018
#include<bits/stdc++.h>
using namespace std;
#define Sheryang main
const int maxn=1e5+7;
typedef long long ll;
const int mod=998244353;

struct node
{
    int a,b,c,d;
    node (int _a,int _b,int _c,int _d)
    {
        a=_a;
        b=_b;
        c=_c;
        d=_d;
    }
};
map<node,int>m;

bool operator < (node i,node j)
{
    if(i.a!=j.a) return i.a<j.a;
    if(i.b!=j.b) return i.b<j.b;
    if(i.c!=j.c) return i.c<j.c;
    return i.d<j.d;
}

ll ans,tot,k,cnt;
void solve(ll x)//因为x是各数位的乘积 所以质因子只有2 3 5 7四种 记录每一种 每次求补集即可
{
    node p(0,0,0,0);
    while(x)
    {
        int t = x % 10;
        if(t == 0) {++ tot; return;}
        if(t == 2) ++ p.a;
        if(t == 3) ++ p.b;
        if(t == 4) p.a += 2;
        if(t == 5) ++ p.c;
        if(t == 6) ++ p.a, ++ p.b;
        if(t == 7) ++ p.d;
        if(t == 8) p.a += 3;
        if(t == 9) p.b += 2;
        x /= 10;
    }
    if(k)
    {
        p.a %= k;
        p.b %= k;
        p.c %= k;
        p.d %= k;
        node q((k - p.a) % k, (k - p.b) % k, (k - p.c) % k, (k - p.d) % k);
        ans -= m[q];
        ++ m[p];
    }
    else
    {
        if(!p.a && !p.b && !p.c && !p.d)
            ans-=cnt,cnt++;
    }
}

int Sheryang()
{
    int n;
    scanf("%d %lld",&n,&k);

    ans=1LL*n*(n-1)/2;
    for(int i=1;i<=n;i++)
    {
        ll x;
        scanf("%lld",&x);
        solve(x);
    }

    if(k) ans-=1LL*(n+n-tot-1)*tot/2;
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sudu6666/article/details/84563559
今日推荐