首先,我们可以得到一个简单的 3 l o g a i 3^{log_{ai}} 3logai的暴力dp+子集枚举,这样是 3 18 3^{18} 318的复杂度,1e8左右,2s的时间本来是妥妥地过的,结果CCF机子太烂跑T了。先给出代码吧。
Code:
inline void Sieve(LL x)
{
Phi[1] = 1;
for (Int i = 2; i <= x; ++ i)
{
if (! Phi[i])
{
Prime[++ Prime[0]] = i;
Phi[i] = i - 1;
}
for (Int j = 1; j <= Prime[0] && Prime[j] * i <= x; ++ j)
{
if (i % Prime[j] == 0)
{
Phi[Prime[j] * i] = Prime[j] * Phi[i];
break;
}
else Phi[Prime[j] * i] = Prime[j] * Phi[i] - Phi[i];
}
}
}
read( n );
for (Int i = 1; i <= n; ++ i)
{
LL t;
read( t );
a[t] ++;
Maxx = Max(Maxx, t);
}
LL Temp = 1, Mi = 0;
while (Temp <= Maxx)
Mi ++, Temp *= 2;
Sieve(1 << Mi);
dp[0] = 1;
for (Int i = 1; i <= (1 << Mi); ++ i)
for (Int j = i; j > (i ^ j); j = (j - 1) & i)
dp[i] = (dp[i] + a[j] * dp[i ^ j]) % Mod;
// for(int i = 0; i <= 3; ++ i)
// printf("dp[%d] = %lld\n", i, dp[i]);
LL Ans = 0;
for (Int i = 0; i <= (1 << Mi); ++ i)
Ans = (Ans + dp[i] * Phi[i + 1]) % Mod;
while (a[0] --)
Ans = Ans * 2 % Mod;
优化
However,这个代码的时间复杂度是不稳妥的(仅对于CCF),这个时候,我们就得使用快速子集变换。