Description
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。
2 ≤ n ≤ 105, 0 ≤ ai, k ≤ 1018
Solution
我们把f分解一下,质数只有2、3、5、7四种。两数相乘是某个自然数的k次幂说明它们指数上和模k为0。由于260小于1018,我们开604的桶直接统计就没了
注意k=0和k=1的情况
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <map>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
typedef long long LL;
const int N=200005;
LL cnt[63][63][63][63],p[N][4];
LL a[N],k;
int n,tot;
void solve1() {
LL ans=1LL*n*(n-1)/2;
rep(i,1,n) {
LL v,x=1; scanf("%lld",&v);
for (;v;v/=10) x=x*(v%10);
if (!x) continue;
a[++tot]=x;
for (;x%2==0;x/=2) p[tot][0]++; p[tot][0]%=k;
for (;x%3==0;x/=3) p[tot][1]++; p[tot][1]%=k;
for (;x%5==0;x/=5) p[tot][2]++; p[tot][2]%=k;
for (;x%7==0;x/=7) p[tot][3]++; p[tot][3]%=k;
}
rep(i,tot+1,n) ans=(ans-(n-i+tot));
n=tot;
rep(i,1,n) {
if ((k-p[i][0]%k)%k<=60&&(k-p[i][1]%k)%k<=60&&(k-p[i][2]%k)%k<=60&&(k-p[i][3]%k)%k<=60) {
ans-=cnt[(k-p[i][0]%k)%k][(k-p[i][1]%k)%k][(k-p[i][2]%k)%k][(k-p[i][3]%k)%k];
}
cnt[p[i][0]][p[i][1]][p[i][2]][p[i][3]]++;
}
printf("%lld\n", ans);
}
void solve3() {
LL ans=(n-1)*n/2,wjp=0;
rep(i,1,n) {
LL v,x=1; scanf("%lld",&v);
for (;v;v/=10) x=x*(v%10);
a[i]=x;
if (x==1) wjp++;
if (!x) continue;
for (;x%2==0;x/=2) p[i][0]++;
for (;x%3==0;x/=3) p[i][1]++;
for (;x%5==0;x/=5) p[i][2]++;
for (;x%7==0;x/=7) p[i][3]++;
}
printf("%lld\n", ans-(wjp-1)*wjp/2);
}
int main(void) {
freopen("data.in","r",stdin);
freopen("myp.out","w",stdout);
scanf("%d%lld",&n,&k);
if (k==0) solve3();
else if (k==1) puts("0");
else solve1();
return 0;
}