noip模拟77
A. 最大或
签到题,随便写.
A_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
#define ll long long int
#define ull unsigned ll
#define lf long double
#define lbt(x) (x&(-x))
#define mp(x,y) make_pair(x,y)
#define lb lower_bound
#define ub upper_bound
#define Fill(x,y) memset(x,y,sizeof x)
#define Copy(x,y) memcpy(x,y,sizeof x)
#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
inline ll read() {
ll w=0; bool cit=1; char ch;
while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
while(isdigit(ch)) w=(w<<3)+(w<<1)+(ch^48),ch=getchar();
return cit?w:-w;
}
} using namespace BSS;
const ll Inf=1e18,N=70;
ll L,R,cnt;
ll val[N];
inline void Pre(){
val[++cnt]=1;
for(ll i=1;(1ll<<i-1)<=Inf;i++)
val[++cnt]=1ll<<i;
}
auto Work=[]()->void{
ll res=0,l=read(),r=read();
for(ll i=cnt;i>=0;i--){
if(((1ll<<i-1)&r)==((1ll<<i-1)&l)) res|=((1ll<<i-1)&r);
else{ res|=(1ll<<i)-1; break; }
}
printf("%lld\n",res);
};
signed main(){
File(maxor);
Pre();
for(int Ts=read();Ts;Ts--) Work();
exit(0);
}
B. 答题
签到题,随便写.
B_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
#define ll long long
#define ull unsigned ll
#define lf double
#define lbt(x) (x&(-x))
#define mp(x,y) make_pair(x,y)
#define lb lower_bound
#define ub upper_bound
#define Fill(x,y) memset(x,y,sizeof x)
#define Copy(x,y) memcpy(x,y,sizeof x)
#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
inline ll read() {
ll w=0; bool cit=1; char ch;
while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
while(isdigit(ch)) w=(w<<3)+(w<<1)+(ch^48),ch=getchar();
return cit?w:-w;
}
} using namespace BSS;
const ll N=45,W=(1ll<<20)+501;
lf p;
ll m,n,U,cnt1,cnt2,alls;
ll val[45],pre[45],dp[40051];
ll bin1[W],bin2[W];
inline void Work1(){
sort(val+1,val+1+n),dp[0]=1;
for(ll i=1;i<=n;i++){
for(ll j=pre[i];j>=val[i];j--)
dp[j]+=dp[j-val[i]];
}
ll res=ceil((1ll<<n)*p);
for(ll i=0;i<=pre[n];i++){
if(res<=dp[i]) printf("%lld\n",i),exit(0);
res-=dp[i];
}
exit(0);
}
auto check=[](ll x)->bool{
ll res=0;
// cout<<"x:"<<x<<endl;
for(ll p1=1,p2=cnt2;p1<=cnt1;p1++){
while(p2 and bin1[p1]+bin2[p2]>x) p2--;
if(bin1[p1]+bin2[p2]<=x) res+=p2;
}
return (1.0*res)/((lf)alls)>=p;
};
inline void Work2(){
ll mid=n>>1,lft=n-mid,S=(1<<mid)-1,T=(1<<lft)-1,res;
for(ll i=0;i<=S;i++){
res=0;
for(ll j=1;j<=mid;j++)
if((i>>j-1)&1) res+=val[j];
bin1[++cnt1]=res;
}
for(ll i=0;i<=T;i++){
res=0;
for(ll j=1;j<=lft;j++)
if((i>>j-1)&1) res+=val[j+mid];
bin2[++cnt2]=res;
}
sort(bin1+1,bin1+1+cnt1),sort(bin2+1,bin2+1+cnt2);
// for(ll i=1;i<=cnt1;i++) cout<<bin1[i]<<' '; puts(" der");
// for(ll i=1;i<=cnt2;i++) cout<<bin2[i]<<' '; puts(" skr");
ll l=0,r=pre[n],mi; res=r,alls=1ll<<n;
while(l<=r){
mi=(l+r)>>1;
if(check(mi)) res=mi,r=mi-1;
else l=mi+1;
}
printf("%lld\n",res),exit(0);
}
signed main(){
File(answer);
ll flag=1;
n=read(),scanf("%lf",&p),U=(1ll<<n)-1,p=min(1.0,p);
for(ll i=1;i<=n;i++){
pre[i]=pre[i-1]+(val[i]=read());
flag&=(val[i]<=1000);
}
Work2() ;
exit(0);
}
C. 联合权值
数据水,考场上 \(bitset\) 乱过了,正解还没打,代码就先不粘了.
C_code
D. 主仆见证了 Hobo 的离别
发现自己看懂了题目之后忘了好多条件.
感觉这题并不是特别难写,考场上仔细思考应该是能想到.
这样的题画图手玩一下就可以了叭..
D_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
#define ll int
#define ull unsigned ll
#define lf long double
#define lbt(x) (x&(-x))
#define mp(x,y) make_pair(x,y)
#define lb lower_bound
#define ub upper_bound
#define Fill(x,y) memset(x,y,sizeof x)
#define Copy(x,y) memcpy(x,y,sizeof x)
#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
inline ll read() {
ll w=0; bool cit=1; char ch;
while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
while(isdigit(ch)) w=(w<<3)+(w<<1)+(ch^48),ch=getchar();
return cit?w:-w;
}
} using namespace BSS;
const ll N=1e6+21;
ll n,m,ops,ts,ids,cnt;
ll head[N],dfn[N],F[N],con[N],siz[N];
struct II { ll u,v,nxt; } e[N<<1];
struct III { ll x,y; } q[N];
auto add=[](ll u,ll v)->void{
e[++ts].u=u,e[ts].v=v;
e[ts].nxt=head[u],head[u]=ts;
};
struct Dsu{
ll fa[N];
ll find(ll x){ return x==fa[x] ? x : (fa[x]=find(fa[x])) ; }
}A,B;
void dfs(ll u){
dfn[u]=++cnt,siz[u]=1;
(con[u]&1) ? A.fa[u]=A.find(F[u]) : A.fa[u]=u ;
(con[u]&2) ? B.fa[u]=B.find(F[u]) : B.fa[u]=u ;
// cout<<u<<' '<<A.fa[u]<<' '<<B.fa[u]<<' '<<dfn[u]<<endl;
for(ll i=head[u];i;i=e[i].nxt){
dfs(e[i].v),siz[u]+=siz[e[i].v];
}
}
signed main(){
File(friendship);
n=read(),ids=n; ll x,y,opt;
for(int Ts=read();Ts;Ts--){
if(opt=read()) q[++ops].x=read(),q[ops].y=read();
else{
opt=read(),y=read(),ids++;
if(y==1){
x=read(),add(ids,x),F[x]=ids,con[x]=3;
continue;
}
for(ll i=1;i<=y;i++)
x=read(),add(ids,x),F[x]=ids,con[x]=opt+1;
}
}
for(ll i=1;i<=ids;i++) if(!F[i]) dfs(i);
// for(ll i=1;i<=ids;i++) cout<<dfn[i]<<' '<<siz[i]<<endl;
for(ll i=1;i<=ops;i++){
x=q[i].x,y=q[i].y;
if(dfn[x]<=dfn[y] and dfn[x]+siz[x]>dfn[y]){
printf("%d\n",(int)(A.find(x)==A.find(y)));
continue;
}
if(dfn[y]<=dfn[x] and dfn[y]+siz[y]>dfn[x]){
printf("%d\n",(int)(B.find(x)==B.find(y)));
continue;
}
puts("0");
}
exit(0);
}
E. 哪一天她能重回我身边
既然每个点都只能有一面向上,那么就可以想到入度为 \(1\) 之类的东西.
那么无解的情况也就很好判断了,也就是一个联通块的点数 \(<\) 边数的时候无解,因为最多只能是一个基环树.
于是无脑大模拟就可以了.
E_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS{
// #define int long long
#define lf double
#define pb push_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define lbt(x) ((x)&(-(x)))
#define Fill(x,y) memset(x,y,sizeof(x))
#define Copy(x,y) memcpy(x,y,sizeof(x))
#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
auto read=[](int w=0,bool cit=0,char ch=getchar()){
while(!isdigit(ch)) cit|=(ch=='-'),ch=getchar();
while(isdigit(ch)) w=(w<<3)+(w<<1)+(ch^48),ch=getchar();
return cit?(-w):w;
};
}using namespace BSS;
#define LL long long
const int mod=998244353,N=2e5+21;
LL tot;
int m,n,ts,ans,cnt;
int head[N],fa[N],pot[N],cir[N],to[N],stk[N],vis[N],up[N],dn[N];
int ve[N<<2];
int siz[N][2];
struct I { int u,v,w,nxt; } e[N<<1];
int find(int x){ return x==fa[x] ? x : fa[x]=find(fa[x]); }
vector<int> vec[N];
auto add=[](int u,int v,int w)->void{
e[++ts].u=u,e[ts].v=v,e[ts].w=w;
e[ts].nxt=head[u],head[u]=ts;
};
void sch(int u){
vis[u]=1;
for(int i=head[u],v;i;i=e[i].nxt){
if(v=e[i].v,vis[v]) continue;
sch(v);
ans+=(!(cir[v]|e[i].w));
}
}
auto solve1=[](int x)->void{
int u,v,w=0,y=0,z=0,tail=0,flag=0;
for(auto i : vec[x]) pot[++cnt]=i;
u=pot[1],stk[++tail]=u,vis[u]=1;
while(!flag){
u=stk[tail],vis[u]=1,w=tail;
for(int i=head[u];i;i=e[i].nxt){
v=e[i].v;
if(ve[i] and (u^v)) continue;
ve[i]=1,ve[i^1]=1,stk[++tail]=v;
if(vis[v] or u==v){
cir[v]=1,to[u]=v,flag=v;
}
break;
}
tail-=(w==tail);
}
v=stk[tail--],w=0;
while(stk[tail]^flag){
u=stk[tail--],cir[u]=1,to[u]=v,v=u;
}
u=stk[tail],cir[u]=1,to[u]=v;
for(int i=1;i<=cnt;i++) vis[pot[i]]=0;
sch(u);
for(int i=1;i<=cnt;i++) vis[pot[i]]=0;
for(int i=1;i<=cnt;i++){
if(cir[pot[i]]){
u=pot[i]; break;
}
}
for(;!vis[u];u=to[u]){
vis[u]=1;
for(int i=head[u];i;i=e[i].nxt){
if((e[i].v^to[u]) or (!e[i].w)) continue;
y++; break;
}
}
for(int i=1;i<=cnt;i++) vis[pot[i]]=0;
for(;!vis[u];u=to[u]){
vis[u]=1;
for(int i=head[u];i;i=e[i].nxt){
if((e[i].v^to[u]) or e[i].w) continue;
z++; break;
}
}
for(int i=1;i<=cnt;i++) w+=cir[pot[i]];
if(min(y,w-y)>min(z,w-z)) swap(y,z);
if(y==w-y) ans+=y,tot=(tot<<1ll)%mod;
else ans+=min(y,w-y);
}; // 基环树
void dfs1(int u,int dad,int rt){
for(int i=head[u],v;i;i=e[i].nxt){
if(v=e[i].v,v==dad) continue;
dfs1(v,u,rt);
up[u]+=up[v]+(!e[i].w);
dn[u]+=dn[v]+e[i].w;
}
}
void dfs2(int u,int dad){
for(int i=head[u],v;i;i=e[i].nxt){
if(v=e[i].v,v==dad) continue;
up[v]+=up[u]-(up[v]+(!e[i].w))+e[i].w;
dn[v]+=dn[u]-(dn[v]+e[i].w)+(!e[i].w);
dfs2(v,u);
}
}
auto solve2=[](int x)->void{
int u=vec[x][0],y=1e9,z=0;
dfs1(u,0,u),dfs2(u,0);
for(auto i : vec[x]){
if(up[i]<y) y=up[i],z=0;
z+=(up[i]==y);
}
ans+=y,tot=1ll*tot*z%mod;
}; // 无环
auto Work=[]()->void{
m=read(),n=m<<1,tot=1,ts=1,ans=0,tot=1; int u,v;
for(int i=1;i<=n;i++){
fa[i]=i,cir[i]=0,pot[i]=0,head[i]=0,vis[i]=0,to[i]=0,up[i]=0,dn[i]=0,stk[i]=0;
siz[i][0]=1,siz[i][1]=0,vec[i].clear();
}
for(int i=1;i<=m;i++){
u=read(),v=read(),add(u,v,0),add(v,u,1);
if(find(u)^find(v)){
siz[find(v)][0]+=siz[find(u)][0];
siz[find(v)][1]+=siz[find(u)][1];
fa[find(u)]=find(v);
}
siz[find(v)][1]++;
}
for(int i=1;i<=ts;i++) ve[i]=0;
for(int i=1;i<=n;i++){
if(find(i)==i and siz[i][0]<siz[i][1]){
return puts("-1 -1"),void();
}
vec[find(i)].pb(i);
}
for(int i=1;i<=n;i++){
if(!head[i]) continue;
if(find(i)==i){
siz[i][0]==siz[i][1] ? solve1(i) : solve2(i) ;
cnt=0;
}
}
printf("%d %lld\n",ans,tot);
};
signed main(){
for(int Ts=read();Ts;Ts--) Work();
exit(0);
}