[CF895C]Square Subsets
题意简述
给定n个数(n\le10^5 ),每个数\le70,在其中选择一个子集,求使其乘积为完全平方数的方法有多少种。
题解
一道状压dp好题。
注意到此题a_i\leq70,
并且一个数是否为完全平方数只与它的质因子奇偶性有关,所以n\leq10^5 是废话,我们只需要用一个桶统计每个数出现的个数就好了。
另外,打表发现70以内质数只有19个,所以想到状压dp。
令dp_{i,mask} 表示考虑到1-70中的第i个数。并且因为一个数是否为完全平方数只与它的质因子奇偶性有关,mask 表示这19 个数的奇偶性,若第j个质数的因数个数为奇数则mask 第j 位为1。
考虑dp方程的转移。
先从1-70 枚举i,若cnt_i (即数i在数组中出现次数)不为零,则枚举mask
显然,当选奇数个数i 时,mask 会发生改变,我们将i分解质因数,mask 变为mask1 , dp_{i,mask1} 可以从dp_{i-1,mask}转移。
当选偶数个i时,mask不会改变, dp_{i,mask} 可以从 dp_{i-1,mask} 转移。
让我们令当前的cnt_i= k,选奇数个的情况 C_k^1+C_k^3+C_k^5+\cdot\cdot\cdot=\sum\limits_{i\leq k,i\equiv1(mod2)}^iC_k^i=2^{k-1} 种
选偶数个的情况有 C_k^0+C_k^2+C_k^4+\cdot\cdot\cdot=\sum\limits_{i\leq k,i\equiv0(mod2)}^iC_k^i=2^{k-1} 种
这两个式子可以用二项式定理证明。
所以dp_{i,mask1}+=dp_{i-1,mask}*2^{k-1}
dp_{i,mask}+=dp_{i-1,mask}*2^{k-1}
如果cnt_i==0 我们就将dp_{i-1}赋值给dp_{i}
我们可以看到,任dp_{i,mask} 只需从dp_{i-1} 中的数转移,我们可以用滚动数组滚掉一维。
这样我们就做完了。
注意开long long
code:
#include<bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define y0 pmt
#define y1 pmtpmt
#define x0 pmtQAQ
#define x1 pmtQwQ
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int > vi;
typedef pair<int ,int > pii;
typedef vector<pii> vii;
const int inf=0x3f3f3f3f, maxn=100007, mod=1e9+7;
const ll linf=0x3f3f3f3f3f3f3f3fLL;
const ll P=19260817;
const int p[]={2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67};//质数表
int n;
ll dp[2][1<<19];
ll cnt[75];
int I=0;
ll h[maxn];//2^k的表
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
int rt;
scanf("%d",&rt);
cnt[rt]++;
}
h[0]=1;
dp[0][0]=1;
for(int i=1;i<=n;i++)h[i]=(h[i-1]<<1)%mod;
for(int i=1;i<=70;i++){
if(cnt[i]==0)continue;
I^=1;//滚动数组
memset(dp[I],0,sizeof(dp[I]));//注意初始化
for(int mask=0 ; mask< (1<<19) ; mask++){
int mask1=mask;
int x=i;
for(int j=0;j<19&&x>=p[j];j++){
while(x%p[j]==0)x/=p[j],mask1^=(1<<j);
}
(dp[I][mask1]+=1LL*dp[I^1][mask]*h[cnt[i]-1]%mod)%=mod;
(dp[I][mask]+=1LL*dp[I^1][mask]*h[cnt[i]-1]%mod)%=mod;
}
}
printf("%I64d\n",(dp[I][0]-1+mod)%mod);
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 《HelloGitHub》第 106 期
· 数据库服务器 SQL Server 版本升级公告
· 深入理解Mybatis分库分表执行原理
· 使用 Dify + LLM 构建精确任务处理应用