题解 P7704【「MCOI-09」Greedy Deletion】
题意
有一个集合 $S_n=\{x|x\in\Bbb{N}_+,x\le n\}$,其权值为 $\prod_{i\in S_n}i$,从集合中删除一数 $x$ 的代价为 $x^k$,若要将其权值变为完全平方数,求最小代价。对 $998244353$ 取模。多组数据。
$T\le5\times10^5$,$1\le n\le\max n\le5\times 10^6$,$0\le k<998244353$
思路
先吐槽一下,这题大概应该放在 T3 的位置...
我们发现完全平方数仅要求其所有质因子的指数为 $1$,所以只删质因数定能将其变为完全平方数。
又因 $a,b,k\ge 2$ 时 $a^k+b^k\le a^kb^k$,所以只删质因数的代价是最少的。
算法 1
可以离线询问,排序,然后对于排完序后的 $n'_i$,将 $n'_{i-1}+1$ 至 $n'_i$ 之间的数分解质因数,算其贡献,最后对询问进行前缀和即可。
时间复杂度 $O(n^{\frac 5 4}+n\log\log n\log \text{mod}+T\log T)$,期望得分 $44$ 分。
算法 2
考虑筛出 $n$ 以内质数的所有倍数,在倍数处计算前缀和贡献,可以使用前向星将质数与其倍数之间连边,将倍数从 $1$ 扫到 $\max n$,再统计是加入 $i^k$ 的贡献还是 $-i^k$ 的贡献。注意,为了防止带上 $\log \bmod$,质数的 $k$ 次幂可以提前预处理。
时间复杂度 $O(n\log\log n+T)$,期望得分 $100$ 分。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
namespace IO{//by cyffff
}
const int N=5e6+10,mod=998244353;
int maxn,k,T,anss[N],qp[N];
ll cur;
bool app[N];
inline int qpow(int x,int y){
int res=1;
while(y){
if(y&1) res=1ll*res*x%mod;
x=1ll*x*x%mod;
y>>=1;
}
return res;
}
bitset<N>p;
int pri[N],cnt;
int head[N],cntg;
struct Edge{
int to,nxt;
}a[N<<2];
inline void add(int u,int v){
cntg++;
a[cntg].to=v;
a[cntg].nxt=head[u];
head[u]=cntg;
}
inline void sieve(int n){
p[1]=1;
for(int i=2;i<=n;i++){
if(!p[i]){
pri[++cnt]=i;
qp[cnt]=qpow(i,k);
for(ll j=i;j<=n;j*=i)
for(int q=j;q<=n;q+=j)
app[q]^=1;
for(int j=i;j<=n;j+=i)
if(app[j])
add(j,cnt),app[j]=0;
}
for(int j=1;j<=cnt&&i*pri[j]<=n;j++){
p[i*pri[j]]=1;
if(i%pri[j]==0)
break;
}
}
for(int i=1;i<=n;i++){
for(int j=head[i];j;j=a[j].nxt)
cur+=((app[a[j].to]^=1)?qp[a[j].to]:mod-qp[a[j].to]);
anss[i]=cur%mod;
}
}
int main(){
T=read(),k=read(),maxn=read();
sieve(maxn);
while(T--){
int n=read();
write(anss[n]);
putc('\n');
}
flush();
}
再见 qwq~

浙公网安备 33010602011771号