题目
一个a[]数组,长度为n,第i个元素ai,
另一个是b[]数组,长度为m,第j个元素bj。
先对每个元素求阶乘,再对数组求乘积,问两个数组最终所得结果是否相等
1<=n,m<=1e5;0<=ai,bj<=1e5;T<=200;n,m总和不超过2e6
思路来源
https://ac.nowcoder.com/acm/contest/923/B
题解
单哈希mod选的好能过,双哈希能过,但这里考虑差分+勒让德定理
如果统计每个数出现的个数,注意ai!会令[1,ai]区间加1
所以维护差分数组dp[],对ai单点+1,对0单点-1(忽略),统计时求后缀和还原
对于每个素因子,如2,会在2 4 6 8 10出现一次 4 8 12出现一次 8 16出现一次
勒让德定理,不断统计每个素因子在最后的出现次数,判等即是判作差是否得0
复杂度O((n/logn)*logn*logn),考虑清空dp数组和O(T*maxn)取max
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int mod=1e9+7;
int t,n,m,v,dp[maxn];
bitset<maxn>np;
bool ok()
{
for(int i=maxn-2;i>=1;--i)
dp[i]+=dp[i+1];
for(int i=2;i<maxn;++i)
{
if(np[i])continue;
ll num=0;
for(ll now=i;now<maxn;now*=i)
{
for(int j=now;j<maxn;j+=now)
num+=dp[j];
}
if(num)return 0;
}
return 1;
}
int main()
{
scanf("%d",&t);
for(int i=2;i<maxn;++i)
for(int j=i+i;j<maxn;j+=i)
np[j]=1;
while(t--)
{
for(int i=1;i<maxn;++i)
dp[i]=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
{
scanf("%d",&v);
dp[v]++;
}
for(int i=1;i<=m;++i)
{
scanf("%d",&v);
dp[v]--;
}
puts(ok()?"equal":"unequal");
}
return 0;
}