首页 > 其他分享 >8.31

8.31

时间:2022-09-01 08:11:24浏览次数:44  
标签:盒子 int 小球 8.31 配对 dp define

ABC131F

题意:

给定\(n\)个点,如果存在一个四边形恰好缺一个点,则能补一个点,最多操作多少次?

所有数字小于等于\(10^5\)

题解:

把行数,列数当作点,把点当作边

对于一个点\((x,y)\),从\(x_i\)向\(y_j\)之间连一条边。

对于恰好缺一个点的情况,这个连通块里有两个行点,两个列点,三条边,缺一条边。

对于四边形满点的情况,这个连通块里有两个行点,两个列点,四条边。

所以一个连通块的贡献是行点数×列点数-边数

\[ans=(\sum a_i*b_i)-n \]

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define double long double
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define lowbit(i) ((i)&(-i))
#define mid ((l+r)>>1)
#define eps (1e-15)
    const int N=1e6+10,mod=1e9+7,inf=2e15;
    void __init(int n=2000) {}
    inline void main()
    {
        int n;cin>>n;
        int maxn=1e5;
        vector<int> f(2*maxn+1),s1(2*maxn+1),s2(2*maxn+1);
        for(int i=1;i<=2*maxn;++i) f[i]=i;
        for(int i=1;i<=maxn;++i) s1[i]=1;
        for(int i=maxn+1;i<=2*maxn;++i) s2[i]=1;
        function<int(int)> find=[&](int k) -> auto
        {
            return f[k]==k?k:f[k]=find(f[k]);
        };
        for(int i=1;i<=n;++i)
        {
            int x,y;
            cin>>x>>y;
            int tx=find(x),ty=find(maxn+y);
            if(tx==ty) continue;
            s1[ty]+=s1[tx];
            s2[ty]+=s2[tx];
            f[tx]=ty;
        }
        int sum=0;
        for(int i=1;i<=2*maxn;++i) if(find(i)==i)
        {
            //cout<<s1[i]<<' '<<s2[i]<<"!!!"<<endl;
            sum+=s1[i]*s2[i];
        }
        cout<<sum-n<<'\n';  
    }
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    red::__init();
    int qwq=1; //cin>>qwq;
    while(qwq--) red::main();
    return 0;
}
/*

*/

ABC134F

题意:

一个\(1\sim n\)的排列\(p\)的怪异度定义为\(\sum_i |p_i-i|\)。

求怪异度为\(m\)的排列的数量,模\(1e9+7\)

\(1\leq n\leq 50,0\leq m\leq n^2\)

题解:

可以转化为有\(n\)个小球和\(n\)个盒子,一一配对,每个小球和自己盒子之间编号的差距和为\(k\)的放球方案数。

设一个不是人能想出来的\(dp\)方程:

\(dp[i][j][k]\)表示前\(i\)个小球中,有\(j\)个球和\(j\)个盒子还没配对呢,当前怪异度为\(k\)

考虑当前处理到的第\(i\)个小球和第\(i\)个盒子:

第一种情况,这两扔这不管,那么又多了一组不配对的球和盒子,而且前面的球和盒子都没被配上,都会贡献一点怪异度

\(dp[i][j][k]->dp[i+1][j+1][k+(2*j)+2]\)

第二种情况,这两贡献了一对配对,那么既可以是这个小球和前面的盒子配对了,也可以是这个盒子和这个小球配对了,或者第\(i\)个小球和第\(i\)个盒子配对了。

\((2*j+1)*dp[i][j][k]->dp[i+1][j][k+2*j]\)

第三种情况,这两贡献了两对配对,盒子和小球都在前面找对象,小球和盒子都有\(j\)种选择

\(j*j*dp[i][j][k]->dp[i+1][j-1][k+(2*j)-2]\)

这样就好了

另外,因为第一种转移\(k\)要额外\(+2\),而\(j\)会\(+1\),第三种转移\(k\)要额外\(-2\),而\(j\)要\(-1\)

最后的答案是\(dp[n][0][m]\),所以,\(+2\)和\(-2\)最后一定会抵消掉,也可以这么写转移

\(dp[i][j][k]->dp[i+1][j+1][k+2*j]\)

\((2*j+1)*dp[i][j][k]->dp[i+1][j][k+2*j]\)

\(j*j*dp[i][j][k]->dp[i+1][j-1][k+2*j]\)

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define double long double
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define lowbit(i) ((i)&(-i))
#define mid ((l+r)>>1)
#define eps (1e-15)
    const int N=1e6+10,mod=1e9+7,inf=2e15;
    void __init(int n=2000) {}
    inline void main()
    {
        int n,m;
        cin>>n>>m;
        vector dp(n+1,vector(n+1,vector<int>(m+1)));
        dp[0][0][0]=1;
        //dp[i][j][k] 前i个球中,有j个球和盒子还没配对,已经有k的价值
        for(int i=0;i<n;++i)
        {
            for(int j=0;j<=n;++j)
            {
                for(int k=0;k<=m;++k)
                {
                    if(k+2*j+2<=m&&j<n)
                    {
                        int &ret=dp[i+1][j+1][k+2*j+2];
                        ret=(ret+dp[i][j][k])%mod;
                    }
                    if(k+2*j<=m)
                    {
                        int &ret=dp[i+1][j][k+2*j];
                        ret=(ret+(2*j+1)*dp[i][j][k]%mod)%mod;
                    }
                    if(k+2*j-2<=m&&k+2*j-2>=0&&j>0)
                    {
                        int &ret=dp[i+1][j-1][k+2*j-2];
                        ret=(ret+j*j%mod*dp[i][j][k]%mod)%mod;
                    }
                }
            }
        }
        cout<<dp[n][0][m]<<'\n';
    }
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    red::__init();
    int qwq=1; //cin>>qwq;
    while(qwq--) red::main();
    return 0;
}
/*
1 2 5 10

*/

标签:盒子,int,小球,8.31,配对,dp,define
From: https://www.cnblogs.com/knife-rose/p/16645178.html

相关文章

  • 8.31 鲜花
    水平已经远远不如同机房人了,于是决定要在魔怔程度追赶!其实感觉魔怔是不好定义的,从qwaszx是魔怔的,到发青蛙是魔怔的,发垒球是魔怔的,写鲜花不知是不是也是魔怔的,波特的魔......
  • 8.31
    全过程考核,好耶 第一章:物联网概论1.衣食住行带来的改变物联网的技术:1..普适运算:随时随地可以进行的运算,物联网智能的理论模型,自然的交互,计算设备小到毫米和纳米级2.......
  • 课堂笔记 8.31 软件开发课
    1.软件和程序的区别:软件可以满足用户的固定需求2.软件类别:按照功能:系统软件应用软件支撑软件(开发使用)按照服务对象:项目软件,产品划分软件规模:微型  小型中型......