省選模擬17
阿新 • • 發佈:2022-02-17
今天考的不是聯考的試題,而是ZZ_zuozhe的題,題目質量好高!!!
第一題,想到了用bitset做,然後發現列舉的有用的只有是1的位,於是想到用set,但是複雜度瓶頸在於轉移時的賦值操作,沒想到可以用主席樹
第二題,媽呀想著是階乘然後就寫成沒階乘了......
第三題,寫了個揹包,於是只有35分
T1 最短路
發現增加一條路就是將一段連續的1變成0,前面加個1,可以用線段樹二分
轉移就是直接賦值,這裡用dij的時候,用set當堆,這樣比較函式比較好寫引數可以改
AC_code
#include<bits/stdc++.h> using namespace std; #define fo(i,x,y) for(int i=(x);i<=(y);i++) #define fu(i,x,y) for(int i=(x);i>=(y);i--) int read(){ int s=0,t=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();} while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();} return s*t; } const int N=1e5+5; const int M=2e5+1e3; const int mod=1e9+7; int ksm(int x,int y){ int ret=1; while(y){ if(y&1)ret=1ll*ret*x%mod; x=1ll*x*x%mod;y>>=1; }return ret; } int mo(int x){return x>=mod?x-mod:x;} int fro[M];int all(int l,int r){if(l==0)return fro[r];return mo(fro[r]-fro[l-1]+mod);} struct ZXS{ struct POT{int ls,rs,sum;}tr[M*100]; int seg; int newpot(int x){tr[++seg]=tr[x];return seg;} void pushup(int x){ //if(!tr[x].ls&&!tr[x].rs)return ; tr[x].sum=mo(tr[tr[x].ls].sum+tr[tr[x].rs].sum); } void ins(int &x,int px,int l,int r,int ql,int qr,int v){ x=newpot(px);if(ql>qr)return ; if(ql<=l&&r<=qr){ tr[x].ls=tr[x].rs=0; if(v)tr[x].sum=all(l,r); else tr[x].sum=0; return ; } int mid=l+r>>1; if(ql<=mid)ins(tr[x].ls,tr[px].ls,l,mid,ql,qr,v); if(qr>mid)ins(tr[x].rs,tr[px].rs,mid+1,r,ql,qr,v); pushup(x);return ; } int query_mxlen(int x,int l,int r,int ql){ if(ql<=l){ if(tr[x].sum==all(l,r))return r; if(l==r||!tr[x].sum)return l-1; int mid=l+r>>1; if(tr[tr[x].ls].sum==all(l,mid))return query_mxlen(tr[x].rs,mid+1,r,ql); else return query_mxlen(tr[x].ls,l,mid,ql); } if(tr[x].sum==all(l,r))return r; if(!tr[x].sum)return ql-1; int mid=l+r>>1,ret=0; if(ql<=mid)ret=query_mxlen(tr[x].ls,l,mid,ql); if(ret==mid||ql>mid)return query_mxlen(tr[x].rs,mid+1,r,ql); else return ret; } bool comp(int x,int y,int l,int r){//x<y true if(tr[x].sum==tr[y].sum)return false; if(tr[x].sum==all(l,r))return false; if(!tr[x].sum)return true; if(tr[y].sum==all(l,r))return true; if(!tr[y].sum)return false; if(l==r)return tr[x].sum<tr[y].sum; int mid=l+r>>1; if(tr[tr[x].rs].sum==tr[tr[y].rs].sum)return comp(tr[x].ls,tr[y].ls,l,mid); else return comp(tr[x].rs,tr[y].rs,mid+1,r); } }zxs; int rt[N]; int n,m,R=2e5+20,s,t; bool vis[N],ist[N]; struct node{ int x; bool operator < (node a)const{ if(zxs.tr[rt[x]].sum==zxs.tr[rt[a.x]].sum)return x<a.x; return zxs.comp(rt[x],rt[a.x],1,R); } }; set<node> st; struct E{int to,nxt,val;}e[M*2]; int head[N],rp; void add_edg(int x,int y,int z){ e[++rp].to=y;e[rp].nxt=head[x]; e[rp].val=z;head[x]=rp; } signed main(){ freopen("hellagur.in","r",stdin); freopen("hellagur.out","w",stdout); n=read();m=read(); fro[0]=1;fo(i,1,R)fro[i]=(fro[i-1]+ksm(2,i))%mod; fo(i,1,m){ int x=read(),y=read(),z=read(); add_edg(x,y,z);add_edg(y,x,z); //if(z==0)cerr<<"SB"<<endl; } s=read();t=read();rt[s]=++zxs.seg; fo(i,1,n)if(i!=s)zxs.ins(rt[i],rt[s],1,R,1,R,1); st.insert(node{s});ist[s]=true; while(st.size()){ int x=st.begin()->x;st.erase(st.begin()); if(vis[x])continue; vis[x]=true;ist[x]=false; for(int i=head[x];i;i=e[i].nxt){ int y=e[i].to,tmp,r,l=e[i].val; if(vis[y])continue; r=zxs.query_mxlen(rt[x],1,R,l); zxs.ins(tmp,rt[x],1,R,l,r,0); zxs.ins(tmp,tmp,1,R,r+1,r+1,1); if(zxs.comp(tmp,rt[y],1,R)){ if(ist[y])st.erase(node{y}); ist[y]=true;rt[y]=tmp; st.insert(node{y}); } } } if(zxs.tr[rt[t]].sum==all(1,R))printf("-1"); else printf("%d",zxs.tr[rt[t]].sum); }
T2 集合
發現有可能的大小是n,n-1,n-2
奇數的話,還有n-3,用異或hash表示
AC_code
#include<bits/stdc++.h> using namespace std; #define ll long long #define fo(i,x,y) for(int i=(x);i<=(y);i++) #define fu(i,x,y) for(int i=(x);i>=(y);i--) int read(){ int s=0,t=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();} while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();} return s*t; } const ll inf=1e18; random_device pyt; mt19937 you(pyt()); ll rd(ll l,ll r){ return rand()%inf; uniform_int_distribution<> ee(l,r); return ee(you)*ee(you); } const int N=1e6+5; int n; unordered_map<ll,int> mp; ll vl[100005],val[N],tmp; int p[100005],cnt,mn[N]; bool vis[N]; void init_p(){ fo(i,2,n){ if(!vis[i]){ p[++cnt]=i; vl[cnt]=rd(1,inf); mn[i]=cnt; } for(int j=1;j<=cnt&&i*p[j]<=n;j++){ vis[i*p[j]]=true;mn[i*p[j]]=j; if(i%p[j]==0)break; } } } int ck2(int n){tmp=0; fo(i,1,n)tmp^=val[i]; fo(i,1,n)if(mp.find(tmp^val[i])!=mp.end()&&mp[tmp^val[i]]!=i)return i; return false; } int ck1(int n){tmp=0; fo(i,1,n)tmp^=val[i]; fo(i,1,n)if((tmp^val[i])==0)return i; return false; } bool ck0(int n){tmp=0; fo(i,1,n)tmp^=val[i]; return !tmp; } signed main(){ freopen("mountain.in","r",stdin); freopen("mountain.out","w",stdout); n=read();int res;srand(time(0)); init_p(); fo(i,1,n){int now=i;ll hs=0; while(now!=1)hs^=vl[mn[now]],now/=p[mn[now]]; val[i]=val[i-1]^hs;mp[val[i]]=i; } if(n&1)n--; if(ck0(n)){ printf("%d\n",n); fo(i,1,n)printf("%d ",i); return 0; } if(res=ck1(n)){ printf("%d\n",n-1); fo(i,1,n)if(i!=res)printf("%d ",i); return 0; } if(res=ck2(n)){ printf("%d\n",n-2);int sm=0; fo(i,1,n)if(i!=res&&i!=mp[tmp^val[res]])printf("%d ",i); return 0; } mp.erase(val[n--]);res=ck2(n); printf("%d\n",n-2);//mp.erase(val[n]); fo(i,1,n)if(i!=res&&i!=mp[tmp^val[res]])printf("%d ",i); return 0; }
T3 食材
這個不可改,根本看不懂題解誒......
QQ:2953174821