F-Shannon Switching Game,H-Wheel of Fortune,584B

79 阅读2分钟

[F-Shannon Switching Game?_"蔚来杯"2022牛客暑期多校训练营10 (nowcoder.com) bfs]

只要J当前走的点可以达到t的路径大于等于2,那么该点就是合法的,所以我们可以直接bfs看看从s到t通过这个约束条件是否还有路径存在就行,若从s开始bfs还需要知道每个点是否可以到达t,但是从t开始就不需要管了,因为从t开始遍历到的点一定都可以到达t,然后就是统计这个点是否是大于等于2条路径了,这个也好处理,一个二重循环就可以知道,另外重边的情况不需要考虑,不管是vector还是前向星都可以直接填边,不会影响最终的结果,之前写的都是单独处理重边,但根本不需要,而且自己好像还处理错了,,,

ll T,n,m,s,t;
ll head[200005],cnt;
struct Edge{
    ll from,to,next;
}edge[200005];
void addedge(ll from,ll to){
    edge[++cnt].from=from;
    edge[cnt].to=to;
    edge[cnt].next=head[from];
    head[from]=cnt;
}
ll ok[105];
void bfs(){
    queue<ll>q;
    q.push(t);
    ok[t]=1;
    while(!q.empty()){
        ll u=q.front();q.pop();
        for(int i=head[u];i;i=edge[i].next){
            ll v=edge[i].to;
            if(ok[v]) continue;
            ll flag=0;
            for(int j=head[v];j;j=edge[j].next){
                if(ok[edge[j].to]) flag++;
            }
            if(flag>=2) ok[v]=1,q.push(v);
        }
    }
    if(ok[s]) printf("Join Player\n");
    else printf("Cut Player\n");
}
int main(){
    scanf("%lld",&T);
    while(T--){
        memset(edge,0,sizeof(edge));
        memset(head,0,sizeof(head));
        cnt=0;
        scanf("%lld%lld%lld%lld",&n,&m,&s,&t);
        for(int i=1;i<=n;i++) ok[i]=0;
        for(int i=1;i<=m;i++){
            ll u,v;
            scanf("%lld%lld",&u,&v);
                addedge(u,v);
                addedge(v,u);
        }
        bfs();
    }
    return 0;
}

[H-Wheel of Fortune_"蔚来杯"2022牛客暑期多校训练营10 (nowcoder.com) 组合数 概率

        一开始想了很久,考虑上随从要如何算概率,好不容易想出个式子来然后去写,写完样例都过不去(幸好没过样例),然后就开始手算第一个样例的概率,是按照自己的式子算的,然后算出的数都可以怀疑人生了,然后问队友第一个样例的概率是多少,一句50%直接让我豁然开朗了,虽然样例一的随从数量是一样的,但是还是觉得随从是没用的,因为随从就是挡枪的,而且是给A和B共同挡枪所以对A和B来说随从的作用是一样的,那就可以忽略了,直接算A和B就可以,那么B被干掉也就是分A被打了0,1,2,,,x-1次,x为A最多可以被打的次数,y为B最多可以被打的次数,那么概率就是C(y+i-1,i)(1/2)^i(1/2)^y,组合数是一共有y+i个空,最后一个一定是B,所以还有y+i-1个空,从这些空里选i个就是多少中顺序了,然后这个题就做出来了

ll a,b,n,x,y;
ll fac[30000005],tw[30000005];
ll C(ll x,ll y){//求组合数模板
    return fac[x]*getinv(fac[y])%mod*getinv(fac[x-y])%mod;
}
int main(){
    fac[0]=1; tw[0]=1;
    //预处理
    for(ll i=1;i<=30000000;i++) fac[i]=fac[i-1]*i%mod,tw[i]=tw[i-1]*2LL%mod;
    tw[30000000]=getinv(tw[30000000]);
    for(int i=29999999;i>=0;i--) tw[i]=2LL*tw[i+1]%mod;
    scanf("%lld",&a);
    x=0,y=0;
    //a的次数
    if(a%10LL!=0LL) x++;
    x+=a/10LL;
    for(int i=1;i<=7;i++){
        ll c;
        scanf("%lld",&c);
    }
    scanf("%lld",&b);
    //b的次数
    if(b%10LL!=0) y++;
    y+=b/10LL;
    for(int i=1;i<=7;i++){
        ll c;
        scanf("%lld",&c);
    }
    ll ans=0;
    for(int i=0;i<x;i++){
        //组合数
        ll res=C((y+i-1LL),i);
        //计算
        ans=(ans+(tw[i]*tw[y]%mod)*res%mod)%mod;
    }
    printf("%lld\n",ans);
    return 0;
}

584B - Kolya and Tanya

可以发现不符合条件的有7种情况,每个n总情况为3^(3*n),不符合情况的有7^(n),所以答案就是两数相减,不要忘了取模,,

ll n;
int main(){
    scanf("%lld",&n);
    ll ans=(qpow(27LL,n)-qpow(7LL,n)+mod)%mod;
    printf("%lld\n",ans);
    return 0;
}