zoukankan      html  css  js  c++  java
  • GKurumi记

    20191007GKurumi爆0记 2

    by GKurumi

    T1、那一天我们许下约定

    题目描述:(保密)

    思路分析,想了10多分钟,dp打了10多分钟,之后发现d原来那么大。

    只能拿30分

    30分代码(程序有点锅,不要贸然复制粘贴):

    #include<bits/stdc++.h>
    using namespace std;
    const int mod=998244353;
    int n,m,d,f[2001][2001];
    int main()
    {
    	cin>>n>>d>>m;
    	while(n&&m&&d)
    	{
    		memset(f,0,sizeof(f));
    		f[0][0]=1;
    		for(int i=1;i<=d;i++)
    		{
    			f[0][i]=1;
    		}
    		for(int i=1;i<=n;i++)
    		{
    			for(int k=1;k<=d;k++)
    			{
    				for(int j=min(m-1,i);j>=0;j--)
    				{
    					if(i>=j)f[i][k]=(f[i][k]+f[i-j][k-1])%mod;
    				}
    			}
    		}
    		cout<<f[n][d]<<endl;
    		cin>>n>>d>>m;
    	}
    	return 0;
    }
    	
    

    之后我们又想如何消掉d(考场先做的T2),我们定义f[ i ] [ j ],第一维存几天,第二维存给多少饼干的方案数。我们可得到一个式子。(f[i][j] = sum^{j - 1}_{k = j - m - 1}f[j - 1][k])

    再往下想,直接遍历还是会超时,我们又需要一个前缀和算出每天给多少饼干的方案数。

    处理完,算一遍方案数,不难想到,n如果小于d时,即使每天给一个的话也会有几天给不到,所以需先判断n于d的大小关系。统计方案就是吧多少天给多少饼干的方案加起来就ok。

    [ans = sum^n_{i = 1}{f[i][j]} imes C binom{i}{d} ]

    这样思路就清晰了

    之后放上代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    int read()
    {
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='0')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch-'0');ch=getchar();}
    	return x*f;
    }
    
    const int mod=998244353;
    int n,m,d,f[2010][2010];
    int sum[4010],ans;
    int ksm(int a,int b)
    {
    	int ans=1;
    	while(b)
    	{
    		if(b&1)
    		{
    			ans=a*ans%mod;
    		}
    		a=a*a%mod;
    		b>>=1;
    	}
    	return ans%mod;
    }
    
    signed main()
    {
    //	freopen("contract.in","r",stdin);
    //	freopen("contract.out","w",stdout);
    	n=read();d=read();m=read();
    	while(n!=0||m!=0||d!=0)
    	{
    		memset(f[1],0,sizeof(f[1]));
    		f[0][0]=1;
    		ans=0;
    		for(int i=1;i<=min(n,m-1);i++)
    		{
    			f[1][i]=1;
    		}
    		for(int i=2;i<=n;i++)
    		{
    			for(int j=0;j<=n;j++)
    			{ 
    				sum[j]=((sum[j-1])%mod+(f[i-1][j])%mod)%mod;
    			}
    			for(int j=1;j<=n;j++)
    			{
    				f[i][j]=(sum[j-1]%mod-sum[max(j-m,0ll)]%mod+mod)%mod;
    			}
    		}
    		int now=d%mod;
    		for(int i=1;i<=min(n,d);i++)
    		{
    			if(i==1)
    			{
    				ans=((ans+now*f[i][n]%mod)%mod);
    				ans%=mod;
    			}
    			else
    			{
    				now=(now%mod*ksm(i,mod-2)%mod*((d-i+1)%mod))%mod;
    				ans%=mod;
    				ans=(ans+f[i][n]%mod*now%mod)%mod;
    			}
    		}
    		cout<<(ans+mod)%mod<<endl;
    		n=read();d=read();m=read();
    	}
    	return 0;
    }
    			
    

    T2、那一天她离我而去

    题目描述:(加密)

    思路清晰,找最小环:

    不说了直接上代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    int t,n,m,ans=0x3f3f3f3f;
    int head[40010],cnt=1,to[40010],val[40010],nxt[40010];
    int read()
    {
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='0')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch-'0');ch=getchar();}
    	return x*f;
    }
    void add(int u,int v,int w)
    {
    	val[++cnt]=w;
    	to[cnt]=v;
    	nxt[cnt]=head[u];
    	head[u]=cnt;
    }
    int dis[40010];
    typedef pair<int,int> p;
    priority_queue<p,vector<p>,greater<p> > q;
    bool vis[40010];
    void dij(int x)
    {
    	memset(dis,0,sizeof(dis));
    	memset(vis,0,sizeof(vis));
    	dis[x]=0;
    	q.push(p(0,x));
    	while(!q.empty())
    	{
    		int u=q.top().second;
    		q.pop();
    		if(vis[u])continue;
    		vis[u]=1;
    		for(int i=head[u];i;i=nxt[i])
    		{
    			int v=to[i];
    			if(dis[v]>dis[u]+val[i])
    			{
    				dis[v]=dis[u]+val[i];
    				q.push(p(dis[v],v));
    				
    			}
    		}
    	}
    }
    signed main()
    {
    	freopen("leave.in","r",stdin);
    	freopen("leave.out","w",stdout);
    	t=read();
    	while(t--)
    	{
    		
    		n=read();m=read();
    		for(int i=1;i<=m;i++)
    		{
    			int u=read(),v=read(),w=read();
    			add(u,v,w);add(v,u,w);
    		}
    		for(int i=head[1];i;i=nxt[i])
    		{
    			int tmp=val[i];
    			val[i]=val[i^1]=0x3f3f3f3f;
    			dij(1);
    			ans=min(ans,dis[to[i]]+tmp);
    			val[i]=val[i^1]=tmp;
    		}
    		
    		if(ans==0x3f3f3f3f)ans=-1;
    		//cout<<ans<<endl;
    		printf("%lld
    ",ans);
    		ans=0x3f3f3f3f;
    		cnt=1;
    		memset(head,0,sizeof(head));
    	}
    	return 0;
    }
    /*
    2
    3 3 
    1 2 1 
    2 3 1 
    3 1 1 
    4 5 
    1 2 2 
    2 3 2 
    3 4 2 
    1 4 2 
    1 3 5
    */
    

    n^2logn可能会T。

    T3、哪一天她能重回我身边

    题目描述:(加密)

    神仙题,我这个蒟蒻是不会了,看题解是换根dp(反正我也没学过)

    大概思路就是:

    第一次dp出以任意点u的答案 (只需要计算让所有边都指向父亲需要反转多少次)。

    第二次dp出以每个点为根的答案。

    取最小值,统计最小值的方案次数。

    特别的: 基环树的方案只可能有1或两种,只需要判断顺逆时针的反转次数是否相同即可(具体来说只需要判断以环上相邻两点分别为根的答案是否相等即可)。

    最后将每个联通块的最小值相加,方案数相乘。

    上代码吧

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #define ll long long
    using namespace std;
    const int MAXN=100100,D=998244353;
    int T;
    int n;
    
    struct node
    {
        int to,nxt;
    }mp[MAXN*2];
    int h[MAXN*2],tot;
    void add(int x,int y)
    {
        mp[++tot].nxt=h[x];
        mp[tot].to=y;
        h[x]=tot;
    }
    
    bool flag;
    int vcnt,ecnt;
    
    bool vis[MAXN*2];
    
    void dfs(int u)
    {
        vcnt++;vis[u]=1;
        for(int i=h[u];i;i=mp[i].nxt)
        {
            int v=mp[i].to;
            ++ecnt;
            if(vis[v]) continue;
            dfs(v);
        }
    }
    
    int s,nxt,id;
    ll num,f[MAXN*2],g[MAXN*2],ans,anscnt;
    
    void dfs1(int u,int fa)
    {
        vis[u]=1;
        for(int i=h[u];i;i=mp[i].nxt)
        {
            int v=mp[i].to;
            if(v==fa) continue;
            if(vis[v])
                s=u,nxt=v,id=i;
            else
            {
                dfs1(v,u);
                f[u]+=f[v]+(i&1);
            }
        }
    }
    
    vector<int> vv;
    
    void dfs2(int u,int fa)
    {
        vv.push_back(g[u]);
        for(int i=h[u];i;i=mp[i].nxt)
        {
            int v=mp[i].to;
            if(v==fa) continue;
            if(i==id||i==(id^1)) continue;
            g[v]=g[u]+((i&1)?-1:1);
            dfs2(v,u);
        }
    }
    
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            tot=1;flag=0;
            memset(h,0,sizeof(h));
            memset(vis,0,sizeof(vis));
            scanf("%d",&n);
            for(int i=1,aa,bb;i<=n;i++)
            {
                scanf("%d%d",&aa,&bb);
                add(bb,aa);add(aa,bb);
            }
            for(int i=1;i<=2*n;i++)
                if(!vis[i])
                {
                    vcnt=ecnt=0;
                    dfs(i);
                    if(ecnt/2>vcnt)
                    {
                        printf("-1 -1
    ");
                        flag=1;
                        break;
                    }
                }
            if(flag) continue;
            memset(vis,0,sizeof(vis));
            memset(f,0,sizeof(f));
            memset(g,0,sizeof(g));
            ans=0;anscnt=1;
            for(int i=1;i<=2*n;i++)
                if(!vis[i])
                {
                    vv.clear();
                    s=nxt=id=0;
                    num=0;
                    
                    dfs1(i,0);
                    g[i]=f[i];
                    dfs2(i,0);
                    
                    if(!id)
                    {
                        sort(vv.begin(),vv.end());
                        for(int j=0;j<vv.size();j++)
                            if(vv[j]!=vv[0]) break;
                            else ++num;
                        ans+=vv[0];
                    }
                    else
                    {
                        id&=1;
                        if(g[s]+(id^1)==g[nxt]+id) num=2;
                        else num=1;
                        ans+=min(g[s]+(id^1),g[nxt]+id); 
                    }
                    anscnt=anscnt*num%D;
                }
            printf("%lld %lld
    ",ans,anscnt);
        }
        return 0;
    }
    

    T3参考G_keng的博客,附上原链接

    谢谢。

  • 相关阅读:
    摇骰子游戏
    那些年,产品提出的无理需求
    cookie中数据无法读取,HttpOnly属性
    vue 使用字典值及其翻译
    微信小程序picker组件两列关联使用方式
    fatal: unable to access 'https://github.com/xxxxxgit/': OpenSSL SSL_connect: Connection was reset in connection to github.com:443
    Oracle数据库以date类型保存日期时 nvalid request: Out of range property; SalesOrder.date'
    Event Handler Content must support at least one class.
    Minimum length not met: value 0 < 1 minimum length
    Oracle中使用hash_hmac() 函数报错问题/以及Oracle遇到Oauth1.0授权和oauth_signature生成规则
  • 原文地址:https://www.cnblogs.com/GKurumi/p/11630227.html
Copyright © 2011-2022 走看看