5.10 NOI 模拟

最近总是管不住自己摆烂,没法像Zwaire一样管住自己,摆完之后会有负罪感,一直恶性循环,认识到了这个问题,我希望能逐渐改正(不对,马上放假了,不如摆烂到放假)

话说GD,HN的老哥都太强了吧,联考根本打不过啊QAQ

T1

建图拆点跑匹配都很容易想到,考场上审题不清导致RE

实际代码可以拿20pts(枚举质数+带花树匹配)

//csl1:边上放的一定是最大公因数的约数 //csl2:首先每个因子是互不干扰的,可以单独计算 //枚举质数,把合法的数字提出来 //无解,一个点周围没有任何点 //有解,中间是两个的,两边是一个的 //可以把图分成一条链或者一个环的形式即可 //反正都要满足,那么随机配一下就好,大胆猜测,存在即合法 //猜测失败,但是可以拆点匹配,不会带花树,随机匹配得搞一下轮数... //但是可用的质数是不是有点多? #include<bits/stdc++.h> #define int long long #define MAXN 1000000 #define MAXM 5005 using namespace std; int Fin[MAXN+5],a[MAXN+5],PRIID,cnt,n,m; map<int,int>id; int l,r,zz,NOW,vis1[MAXM],q[MAXM],pre[MAXM],h[MAXM],fa[MAXM],c[MAXM],fl[MAXM]; vector<int>e[MAXM]; int find(int x) { return fa[x]==x?x:fa[x]=find(fa[x]); } int lca(int u,int v) { for(zz++;fl[u]^zz;swap(u,v)) if(u) fl[u]=zz,u=find(pre[h[u]]); return u; } void blo(int u,int v,int rt) { for(;find(u)^rt;u=pre[v]) { pre[u]=v,fa[u]=fa[v=h[u]]=rt; if(c[v]&1) c[q[++r]=v]=2; } } bool bfs(int u) { for(iota(fa,fa+1+NOW,0),fill(c,c+1+NOW,0),c[q[l=r=1]=u]=2;l<=r;u=q[++l]) for(int v:e[u]) if(!c[v]) { pre[v]=u; c[v]=1; c[q[++r]=h[v]]=2; if(!h[v]) { for(;u;v=u) u=h[pre[v]],h[h[v]=pre[v]]=v; return 1; } } else if(c[v]==2) { int l=lca(u,v); blo(u,v,l); blo(v,u,l); } return 0; } map<int,int>pri; vector<int>rd[MAXN],ID[MAXN]; map<int,vector<pair<int,int> > >Eve; map<pair<int,int>,int>RDNUM; signed main() { scanf("%lld%lld",&n,&m); for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); } for(int i=1,u,v;i<=m;i++) { scanf("%lld%lld",&u,&v); // if(n==10&&i>24)cout<<u<<" "<<v<<"\n"; rd[u].push_back(v); rd[v].push_back(u); if(u>v) swap(u,v); RDNUM[make_pair(u,v)]=i; Fin[i]=1; } for(int i=1;i<=n;i++) { int res=a[i]; map<int,int>Had; for(int j=2;j*j<=a[i];j++) { if(res%j==0) { while(res%j==0) res/=j,Had[j]++; } } if(res!=1) Had[res]++; for(map<int,int>::iterator it=Had.begin();it!=Had.end();it++) { if(!id[it->first]) id[it->first]=++PRIID,pri[PRIID]=it->first; Eve[id[it->first]].push_back(make_pair(i,it->second)); } } if(n>10)return 0; for(int i=1;i<=PRIID;i++) { if(Eve[i].size()) { memset(h,0,sizeof(h)); int cnt=0; map<int,int>bc; for(int j=0;j<Eve[i].size();j++) { int now=Eve[i][j].first; int num=Eve[i][j].second; } for(int j=1;j<=n;j++) ID[j].clear(); for(int j=0;j<Eve[i].size();j++) { int now=Eve[i][j].first; int num=Eve[i][j].second; if(num==1) { ID[now].push_back(++cnt); bc[cnt]=now; } if(num==2) { ID[now].push_back(++cnt); bc[cnt]=now; ID[now].push_back(++cnt); bc[cnt]=now; } } for(int j=1;j<cnt;j++) e[j].clear(); for(int j=0;j<Eve[i].size();j++) { int now=Eve[i][j].first; int num=Eve[i][j].second; for(int k=0;k<rd[now].size();k++) { int y=rd[now][k]; for(int id1=0;id1<ID[now].size();id1++) { for(int id2=0;id2<ID[y].size();id2++) { e[ID[now][id1]].push_back(ID[y][id2]); } } } } int Ans=0; NOW=cnt; for(int j=1;j<=cnt;j++) if(!h[j]&&bfs(j)) ++Ans; // printf("Ans:%lld %lld %lld\n",pri[i],cnt,Ans); for(int j=1;j<=cnt;j++) { int now=bc[j]; int y=bc[h[j]]; if(now>y) continue; Fin[RDNUM[make_pair(now,y)]]*=pri[i]; } if(cnt!=Ans*2) { cout<<-1; return 0; } } } for(int i=1;i<=m;i++) { cout<<Fin[i]<<"\n"; } }

考虑暴力枚举每个出现的质数的复杂度是O(Num×n3)只能过第一部分

在这里需要优化这一过程,首先考虑枚举质数,首先考虑选择一个数,什么时候可以代替这个质数,首先质数两两互质,正因为两两互质我们就可以每一个都跑一遍不影响

而且我们需要每个质数都满足,那么我们可以尝试把一些质数乘到一起看做一个新的质数跑一遍相同的过程就好了,至于乘起来需要满足什么条件,首先新的数字也要满足独立(不只是两两互质),然后对于取出来的数进行匹配就好了

T2

答案是C(n1,k1)×ϕ(n)

其实对于组合数敏感一点能猜出来,可惜我并没有,还是需要加强练习

话说我每次都是被这种猜结论题区分,心态炸裂

T3

考场上想到了回滚莫队+并查集O(nn)做法,实现麻烦就写了两个sub的暴力

下了场一看,O(nn)只能45pts...

正解待补


__EOF__

本文作者Eternal_Battle
本文链接https://www.cnblogs.com/Eternal-Battle/p/16255795.html
关于博主:这个世界除了你,都知道我喜欢你
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Gnomeshgh_k  阅读(42)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示