1. 程式人生 > >Wannafly挑戰賽29 B 白井黑子 (數論+map)

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;
}