codeforces 461 D Appleman and Complicated Task

29 篇文章 0 订阅
28 篇文章 0 订阅

Descritpion


这里写图片描述

Solution


这题和之前没改出来的矩阵游走思想是类似的,即唯一确定的第一行确定了整个矩阵。那么可以设第一行为未知数,讨论一下其余位置的取值情况。可以发现(0,k)能影响到的点满足是连续的奇数或连续的偶数。那么抽出奇偶点然后就能用前缀异或和做了。
题目转化为:给定一些限制条件形如sum[l-1]^sum[r]=0或1,求可行方案数
可以回想2sat的做法,把点i拆为i和i’表示i取0或1,讨论一下并查集合并判无解就ok

Code


#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <stdlib.h>
#include <time.h>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define fill(x,t) memset(x,t,sizeof(x))

typedef long long LL;

const int MOD=1000000007;
const int N=200005;

int fa[N],a[N],b[N];

LL ksm(LL x,LL dep) {
    if (dep==0) return 1;
    if (dep==1) return x;
    LL tmp=ksm(x,dep/2);
    if (dep%2) return tmp*tmp%MOD*x%MOD;
    return tmp*tmp%MOD;
}

int get_father(int now) {
    return (fa[now]==-1)?(now):(fa[now]=get_father(fa[now]));
}

bool merge(int x,int y) {
    x=get_father(x); y=get_father(y);
    if (x==get_father(x^1)) return false;
    if (y==get_father(y^1)) return false;
    if (x!=y) fa[x]=y;
    return true;
}

bool check(int x,int y,int z) {
    if (z==0) {
        return merge(x*2,y*2)&&merge(x*2+1,y*2+1);
    } else if (z==1) {
        return merge(x*2,y*2+1)&&merge(x*2+1,y*2);
    }
}

int main(void) {
    fill(fa,-1);
    int n,m; scanf("%d%d",&n,&m);
    rep(i,1,m) {
        int x,y; scanf("%d%d",&x,&y);
        x-=1; y-=1;
        char ch[2]; scanf("%s",ch);
        int l=std:: abs(x-y);
        int r=std:: min(x+y,2*(n-1)-(x+y));
        if (!check(l,r+2,ch[0]=='o')) {
            puts("0");
            return 0;
        }
    }
    LL ans=0;
    rep(i,0,n*2+3) if (get_father(i)==i) ans++;
    LL prt=ksm(2,ans/2-2);
    printf("%lld\n", prt);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值