Orz千古神犇ydc的题解
自从我发现这个不是基环无向树就不想做了
没想到数据好水
强行把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; }