牛客练习赛62(基于官方题解的补题 A ~ D)

难度中等,需要一定的分析,主要是跟榜跟的心态爆炸了,感觉A C D 比B好想一些

A-牛妹的游戏

题意:给你n节点m条边的无向图,问原图和补图是否有三元环。

做法:知道不合法的肯定很少,但不知道怎么暴力求三元环(这里的确是菜了,其实很简单,就枚举三个点i-j j-k k-i 就可以了)

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define per(i,a,b) for(int i=a;i>=(b);--i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=100;

int n,m,flag;
int dp[N][N];


void solve()
{
    scanf("%d%d",&n,&m);
    if(n>18){
        int u,v;
        rep(i,1,m) scanf("%d%d",&u,&v);
        puts("yes");
        return ;
    }
    mem(dp,0);
    rep(i,1,m){
        int u,v;
        scanf("%d%d",&u,&v);
        dp[u][v]=dp[v][u]=1;
    }
    flag=0;
    for(int i=1;i<=n;++i){
        for(int j=i+1;j<=n;++j){
            for(int k=j+1;k<=n;++k){
                int t=dp[i][j]+dp[j][k]+dp[k][i];
                if(t==0||t==3) flag=1;
            }
        }
    }
    printf("%s\n",flag?"yes":"no");

}
int main()
{
	int _;cin>>_;while(_--)
	solve();
}

B-病毒扩散

直接按照题意来很难写,需要转换:

能想到这个题意模型有点不容易。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define per(i,a,b) for(int i=a;i>=(b);--i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=5e3+10;
const ll mod=998244353 ;
ll f[N];
void init()
{
   f[0]=1;
   rep(i,1,N-1) f[i]=f[i-1]*i%mod;
}
ll powmod(ll a,ll b)
{
    ll res=1;
    for(;b;b>>=1){
        if(b&1) res=res*a%mod;
        a=a*a%mod;
    }
    return res;
}
ll C(int n,int m)
{
    return f[n]*powmod(f[m],mod-2)%mod*powmod(f[n-m],mod-2)%mod;
}
void solve()
{
    int x,y,t;
    scanf("%d%d%d",&x,&y,&t);
    if(t<x+y){
        puts("0");return ;
    }
    ll ans=C(t,x+y)*C(x+y,x)%mod;
    printf("%lld\n",ans);
}
int main()
{
	init();
	int _;cin>>_;while(_--)
	solve();
}

C-牛牛染颜色

做法,经典树形dp:dp[u][0]代表u这个节点不为黑色的方案数,dp[u][1]代表u这个节点变为黑色节点的个数

dp[u][1]的方案数好计算,dp[u][1]=\prod(dp[v][0]+dp[v][1])

就是这个dp[u][0]想了半天没想到怎么推过来

看官方题解吧:

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define per(i,a,b) for(int i=a;i>=(b);--i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const ll mod=1e9+7;
const int N=1e6+10;
struct node
{
    int v,ne;
}e[2*N];
int head[N],cnt;
int n;
ll dp[N][2];
void add(int u,int v)
{
    e[++cnt]={v,head[u]};
    head[u]=cnt;
    e[++cnt]={u,head[v]};
    head[v]=cnt;
}
void dfs(int u,int fa)
{
    dp[u][0]=1;
    dp[u][1]=1;
    for(int i=head[u];i;i=e[i].ne){
        int v=e[i].v;
        if(v==fa) continue;
        dfs(v,u);
        dp[u][1]=dp[u][1]*(dp[v][0]+dp[v][1])%mod;
        dp[u][0]=(dp[u][0]+dp[v][1]+dp[v][0]-1)%mod;
    }
}
void solve()
{
    scanf("%d",&n);
    rep(i,2,n)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);
    }
    dfs(1,-1);
    printf("%lld\n",(dp[1][1]+dp[1][0])%mod);
}
int main()
{
	//int _;cin>>_;while(_--)
	solve();
}

D-牛牛的呱数

题意:

没看到数据范围,没想到p这么的小

其实就是特别简单的bfs一下,将所有的模数全部覆盖即可。每次bfs取出当前数now  那就从n个里面进行连接即可。。

#include<bits/stdc++.h>
using namespace std;
const int N=2e2+10,M=1e6+10;
typedef long long ll;
ll dp[N],a[N],mod,f[M];
int vis[N],len[N],n;
int main()
{
    cin>>n>>mod;

    f[0]=1;
    for(int i=1;i<M;++i) f[i]=f[i-1]*10%mod;
    for(int i=0;i<N;++i) dp[i]=1e18+10;

    for(int i=1;i<=n;++i){
        string s;cin>>s;
        int now=0;
        for(int j=0;j<s.size();++j)now=(now*10+s[j]-'0')%mod;

        a[i]=now;
        len[i]=s.size();
        dp[now]=min(dp[now],1ll*len[i]);
    }

    queue<int>que;
    for(int i=0;i<mod;++i) if(dp[i]<1e18) que.push(i),vis[i]=1;

    while(que.size()){
        int now=que.front();que.pop();
        vis[now]=0;
        for(int i=1;i<=n;++i){
            int ne=(now*f[len[i]]+a[i])%mod;
            if(dp[ne]>dp[now]+len[i]){
                dp[ne]=dp[now]+len[i];
                if(vis[now]==0){
                    vis[ne]=1;
                    que.push(ne);
                }
            }
        }

    }
    if(dp[0]==1e18+10)dp[0]=-1;
    printf("%lld\n",dp[0]);
}
发布了535 篇原创文章 · 获赞 71 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_41286356/article/details/105744853