给定n序列An,从序列中选若干个数,使得乘积为完全平方数,有多少种方案。
两个方案不同仅当选择的位置不同。方案数对1e9+7取模。
第一行一个整数n,n<=100000
第二行n个整数表示Ai,Ai<=70
输出方案数对1e9+7取模后的值
4
1 1 1 1
15
Sample input2
4
2 2 2 2
Sample output2
7
Sample input3
1
36
Sample output3
1
由线性基的性质,选出最大线性无关组以后,任选不属于无关组的元素后都能构成合法的方案,因此答案为pow(2,n-m)-1,其中,m为无关组的秩即大小
对于个数而言:3^3*3与3^5*3等价,类似的:
由唯一分解定理n=p1^k1……pm^km,我们预处理出1~70每个数包含的质因数,显然,若数n含偶数个数质因子p,则p可以忽略,因此我们只用记录每个数所含有的奇数个的质因子,注意到1~70只有19个质数,直接压位即可
#include
using namespace std;
#define Inc(i,L,r) for(register int i=(L);i<=(r);++i)
#define Red(i,r,L) for(register int i=(r);i>=(L);--i)
#define ll long long
#define Mod (int)(1e9+7)
int pri[]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67};//70以内的质数
int n,fac[77];
struct Linear_Basis{
int p[37];
inline bool insert(int k){
Red(i,31,0){
if(!(k>>i))continue;
if(!p[i]){p[i]=k;break;}
k^=p[i];
}
return k>0;
}
}xxj;
inline void init(){
Inc(i,1,70){
int Fk=i;
Inc(j,1,19){
int num=0;
for(;Fk%pri[j]==0;Fk/=pri[j])++num;
if(num&1)fac[i]|=(1<<(j-1));//压位,表示i有没有pri[j]这个质因数且个数为奇数
}
}
}
inline ll Quick(ll x,int k){
ll ans=1;
while(k){
if(k&1)ans=ans*x%Mod;
k>>=1;
(x*=x)%=Mod;
}
return ans;
}
inline void solv(){
scanf("%d",&n);
int num=0;
Inc(i,1,n){
int idx;scanf("%d",&idx);
if(xxj.insert(fac[idx]))++num;
}
cout<<(Quick(2,n-num)%Mod-1)%Mod<<"\n";
}
int main(){
init();
solv();
return 0;
}