四连测Day3

题目链接:https://pan.baidu.com/s/1_vsHfMI_qO-9IDxmFLkHfg 密码: uza8

T1:

小奥的一笔画,判连通性,查奇偶点即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
inline long long read()
{
    long long f=1,ans=0;char c;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
long long t;
long long n,m;
struct node{
    long long x,y;
    long long nex;
}s[200001];
long long head[100001];
long long cnt=1;
void add(long long a,long long b)
{
    s[cnt].x=a,s[cnt].y=b;
    s[cnt].nex=head[a];head[a]=cnt++;
}
long long xx[100001];
long long book[100001];
bool f;
void dfs(long long bh,long long ans)
{
    for(long long i=head[bh];i!=-1;i=s[i].nex) 
    {
        if(book[s[i].y]==0)
        {
            book[s[i].y]=1;
            dfs(s[i].y,ans+1);
        }
    }
    return;
}
int main()
{
    t=read();
    while(t--)
    {
        memset(head,-1,sizeof(head));
        memset(book,0,sizeof(book));
        memset(s,0,sizeof(s));
        memset(xx,0,sizeof(xx));
        n=read(),m=read();
        cnt=1;
        for(long long i=1;i<=m;i++)
        {
            long long u=read(),v=read();
            add(u,v),add(v,u);
            xx[u]++,xx[v]++;
        }
        f=true;
        book[1]=1;
        dfs(1,1);
        for(int i=1;i<=n;i++)
            if(book[i]==0) {f=false;break;}
        if(f==false) 
        {
            cout<<"NO"<<endl;
            continue;
        }
        bool ssss=true;long long ans=0;
        for(long long i=1;i<=n;i++)
        {
            if(xx[i]%2==1) ans++;
            if(xx[i]==0)
            {
                ssss=false;
                cout<<"NO"<<endl;
                break;
            }
            if(ans>2)
            {
                ssss=false;
                cout<<"NO"<<endl;
                break;
            }
        }
        if(ssss) cout<<"YES"<<endl;
    }
    return 0;
}
/*
1
8 9
1 2
1 3
2 3
3 7
3 8
3 4
4 5
5 6
3 8
*/
View Code

T2:

状压dp,dp[i][j]:i在二进制有0的位数表示这个人希望已被破灭,1表示这个希望仍在。j表示前j个人(被期望活的人m)。总体表示在逆元之后的值

显然,dp[i][j+1]=(dp[i][j]*inv)%mod(j+1这个人还活着)

           而j+1死的时候:dp[i&t1][j+1]=(dp[i][j]*inv)%mod //ti表示除了希望破灭的人的二进制数,从而表示出来j+1死后别人的希望

          因为每种可能都占1/2,所以每次取前面dp[i][j]的1/2

         dp[(1<<n)-1][0]=1,因为这是每一个都有希望

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define inv 499122177
#define mod 998244353
#define low_bit(x) x&-x
using namespace std;
inline long long read()
{
    long long f=1,ans=0;char c;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
long long cx(long long s)
{
    long long c=0;
    while(s!=0)
    {
        long long sry=low_bit(s);
        s-=sry;
        c++;
    }
    return c;
}
long long n,m,dp[35][100001],ans[40]; 
long long s[6][100001];
int main()
{
    n=read(),m=read();
    for(long long i=1;i<=n;i++)
    {
        long long x=read();
        long long xx;
        for(long long j=1;j<=x;j++) xx=read(),s[i][xx]=1;
    }
    dp[(1<<n)-1][0]=1;
    for(long long i=0;i<m;i++)
    {
        for(long long j=(1<<n)-1;j>=0;j--)
        {
            dp[j][i+1]+=(dp[j][i]*inv)%mod;
            dp[j][i+1]%=mod;
            long long t=(1<<n)-1;
            for(long long k=1;k<=n;k++) 
                if(s[k][i+1]==1) t-=(1<<k-1);
            dp[j&t][i+1]+=(dp[j][i]*inv)%mod;    
            dp[j&t][i+1]%=mod;
        }
    }
    for(long long i=0;i<=(1<<n)-1;i++)
    {
        (ans[cx(i)]+=dp[i][m])%=mod;
    }
    for(long long i=0;i<=n;i++) printf("%d ",ans[i]);
}
View Code
原文地址:https://www.cnblogs.com/si-rui-yang/p/9461386.html