自从我发现这个不是基环无向树就不想做了
没想到数据好水
强行把NP的题出成普通题
HN的出题人真是不负责任
(另:这题debug真麻烦)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int N=1000000+5;
const int M=1000000;
const int E=190000;
const int p=(1e9)+7;
typedef long long ll;
struct Edge{int to,next;}e[E<<1];
int head[N],cnt;
void ins(int u,int v){
e[++cnt]=(Edge){v,head[u]};head[u]=cnt;
}
void insert(int u,int v){
ins(u,v);ins(v,u);
}
int gcd(int a,int b){
return b?gcd(b,a%b):a;
}
ll sqr(ll x){return x*x;}
void pre(){
for(int i=1;i<=M/2;i++)
for(int j=i+1;j<=M/2/i&&sqr(j)-sqr(i)<=M;j++)
if((i&1)!=(j&1)&&gcd(i,j)==1)
insert(2*i*j,sqr(j)-sqr(i));
}
int tot[N];
vector<int>S;
bool inS[N],ch[N];
void insert(int x){
if(!inS[x]){
inS[x]=1;
S.push_back(x);
}
}
int dfn[N],dfs_clock;
int vis[N],T;
bool check(int u,int fa){
vis[u]=T;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;if(!tot[v]||v==fa)continue;
if(ch[u]&&ch[v])return false;
if(vis[v]!=T){
if(!check(v,u))return false;
}
}
return true;
}
void dfs(int u,int fa){
dfn[u]=++dfs_clock;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;if(!tot[v]||v==fa)continue;
if(!dfn[v])dfs(v,u);
else if(dfn[v]<dfn[u]){
insert(u);insert(v);
}
}
}
ll f[N][2],xp[N];
void dp(int u,int fa){
vis[u]=T;
f[u][0]=1;
f[u][1]=(xp[tot[u]]-1+p)%p;
if(inS[u]){
if(ch[u])f[u][0]=0;
else f[u][1]=0;
}
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;if(!tot[v]||v==fa)continue;
if(vis[v]!=T)dp(v,u);
else continue;
f[u][0]=f[u][0]*(f[v][0]+f[v][1])%p;
f[u][1]=f[u][1]*f[v][0]%p;
}
}
void DFS(int i,int m,int u,ll &ans){
if(i==m){
T++;
if(check(u,-1)){
T++;
dp(u,-1);
ans=(ans+f[u][0]+f[u][1])%p;
}
}else{
ch[S[i]]=0;
DFS(i+1,m,u,ans);
ch[S[i]]=1;
DFS(i+1,m,u,ans);
}
}
ll solve(int u){
S.clear();
dfs(u,-1);
int m=S.size();
ll ans=0;
DFS(0,m,u,ans);
return ans;
}
int main(){
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
pre();
int n;scanf("%d",&n);
xp[0]=1;
for(int i=1;i<=n;i++)xp[i]=(xp[i-1]<<1)%p;
while(n--){
int h;scanf("%d",&h);
tot[h]++;
}
ll ans=1;
for(int i=1;i<=M;i++)
if(tot[i]&&!dfn[i])ans=ans*solve(i)%p;
ans=(ans-1+p)%p;
printf("%lld\n",ans);
return 0;
}