2019中山大学程序设计竞赛(HDU 6511-6521)

传送门:杭电6511-6521

目录

HDU6511 Min-Max

HDU6512 Triangle

HDU6513 Reverse it 

HDU6514 Monitor

HDU6515 Coding problem

HDU6516 Network

HDU6517 Bring Bring big teacher brother

HDU6518 Clumsy Keke

HDU6519 Enlarge it

HDU6520 Silly Keke

HDU6521 Party


 

HDU6511 Min-Max

题意:有一个长度为n的随机排列以及m个min、max操作。问最后一个操作的结果的期望 * n! 的结果。

思路:把一组数组按大于等于k与否用1\0表示,再按操作来一遍,如果结果为1,说明可行。而如果这个01数组有x个1,那么它对应的正常数组有x!*(n-x)!个。

#include
#include
#include
#define ll long long
using namespace std;
bool a[1<<16][16];
ll fac[16];
bool b[1001];
int n,m;
struct op{
    bool oper,flagx,flagy;//oper表示是否max,flag表示是否数组a、b,
    int x,y;
}op[1001];
void pre()
{
    memset(a,0,sizeof(a));
    int x=1<>=1)
            a[i][j]=t&1;
}
void getfac()
{
    fac[0]=1;
    for(int i=1;i<=15;i++)
    {
        fac[i]=fac[i-1]*(ll)i;
    }
}
bool Find(int i)  //对a[i]数组做模拟运算
{
    for(int j=1;j<=m;j++)
    {
        if(op[j].oper)
        {
            if(op[j].flagx&&op[j].flagy) b[j]=max(a[i][op[j].x],a[i][op[j].y]);
            else if(op[j].flagx&&!op[j].flagy) b[j]=max(a[i][op[j].x],b[op[j].y]);
            else if(!op[j].flagx&&!op[j].flagy) b[j]=max(b[op[j].x],b[op[j].y]);
            else b[j]=max(b[op[j].x],a[i][op[j].y]);
        }
        else
        {
            if(op[j].flagx&&op[j].flagy) b[j]=min(a[i][op[j].x],a[i][op[j].y]);
            else if(op[j].flagx&&!op[j].flagy) b[j]=min(a[i][op[j].x],b[op[j].y]);
            else if(!op[j].flagx&&!op[j].flagy) b[j]=min(b[op[j].x],b[op[j].y]);
            else b[j]=min(b[op[j].x],a[i][op[j].y]);
        }
    }
    return b[m];
}
int getnum(int i)
{
    int ans=0;
    for(int j=1;j<=n;j++)
        if(a[i][j]) ans++;
    return ans;
}
int main()
{
    string str;
    char x,y;
    int p,q;
    getfac();
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        pre();
        ll ans=0;
        for(int i=1;i<=m;i++)
        {
            cin>>str>>x>>p>>y>>q;
            if(str=="max") op[i].oper=1;
            else op[i].oper=0;
            if(x=='a') op[i].flagx=1;
            else op[i].flagx=0;
            if(y=='a') op[i].flagy=1;
            else op[i].flagy=0;
            op[i].x=p;op[i].y=q;
        }
        for(int i=0;i<(1<

HDU6512 Triangle

题意:给你n根棍子,问你是否有其中三根可以组成三角形。

思路:不能组成三角形的数至少构成斐波那契数列。故我们可以算出2的32次方对应第x个斐波那契数,那么当输入n>x时,必然输出YES,否则进行排序,判断是否有a[i]+a[i+1]>a[i+2]。

//第50个斐波那契数已经超过int的限度了。
//如果用三次循环和break也能通过。
#include
#include
#include
#include
#define ll long long
using namespace std;
int main()
{
    int n;
    int a[5000005];
    while(cin>>n)
    {
        for(int i=0;i50) cout<<"YES"<a[i+2])
                {
                    flag=1;
                    break;
                }
            if(flag) cout<<"YES"<

HDU6513 Reverse it 

题意:有一个n行m列的卡牌阵,每个位置是0或1,0代表卡牌背面朝上,1代表卡牌正面朝下。每次可以选择一个小矩阵,把这个矩阵内所有卡牌翻转,问最后可以得到多少本质不同的卡牌阵。

HDU6514 Monitor

题意:在一个面积不超过n*m的矩形上,有p个矩形A,问之后的q个矩形B能否被之前的A全部覆盖。

思路:数据范围超大,用到了二维前缀和,所谓二维前缀和既是v[i,j]表示从(0,0)到(i,j)的面积

#include
#include
#include
#include
#include
#define ll long long
#define MAX 10000007
using namespace std;
int v[MAX];
int m,n;
void add(int i,int j,int k)
{
    if(i>m||j>n) return;
    v[(i-1)*n+j]+=k;
}
int query(int i,int j)
{
    if(i==0||j==0) return 0;
    return v[(i-1)*n+j];
}
void Print()
{
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=n;j++) cout<>m>>n)
    {
        memset(v,0,sizeof(v));
        cin>>k;
        while(k--)
        {
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            add(x1,y1,1);
            add(x2+1,y2+1,1);
            add(x1,y2+1,-1);
            add(x2+1,y1,-1);
        }
        //二维前缀和
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
                v[(i-1)*n+j]+=query(i-1,j)+query(i,j-1)-query(i-1,j-1);
        //Print();//确定某一点有无被覆盖
        for(int i=1; i<=n*m; i++)
            if(v[i]) v[i]=1;
        //再求前缀和
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
                v[(i-1)*n+j]+=query(i-1,j)+query(i,j-1)-query(i-1,j-1);
        cin>>k;
        while(k--)
        {
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            int tmp=query(x2,y2)+query(x1-1,y1-1)-query(x1-1,y2)-query(x2,y1-1);
            if(tmp==((x2-x1+1)*(y2-y1+1))) cout<<"YES"<

HDU6515 Coding problem

题意:将字符串每个字符ASCII的二进制翻转码组成的字符串以每6个一组输出。

思路:模拟

#include
#include
#include
#include
#include
#define ll long long
#define p (i*8+j)/6
using namespace std;
int main()
{
    string a;
    int ans[400004];
    while(cin>>a)
    {
        memset(ans,0,sizeof(ans));
        int n=a.length();
        for(int i=0;i>=1)
                ans[p]=(ans[p]<<1)+(a[i]&1);

        for(int i=0;i<(n/3*4);i++)
            cout<

HDU6516 Network

HDU6517 Bring Bring big teacher brother

HDU6518 Clumsy Keke

题意:给定一个立方堆的三视图,求它的体积(有多种可能则输出最大)。

思路:如果下面的代码不好理解的话,可以考一下切割,即建立一个v[100][100][100],初始为1,慢慢切割,最后统计。

#include
#include
#include
#include
#include
#define ll long long
#define p (i*8+j)/6
using namespace std;
int main()
{
    int x,y,z;
    while(cin>>x>>y>>z)
    {
        int ans=0;
        bool f[100][100],t[100][100],s[100][100];
        for(int i=0;i>f[i][j];
        for(int i=0;i>t[i][j];
        for(int i=0;i>s[i][j];
        for(int i=0;i

HDU6519 Enlarge it

题意:输入一个字符矩阵,把它放大k倍输出。

#include
#include
#include
#include
#include
#define ll long long
using namespace std;
int main()
{
    int m,n,k;
    char a[100][100],b[1000][1000];
    while(cin>>m>>n>>k)
    {
        for(int i=0;i>a[i][j];
        for(int i=0;i

HDU6520 Silly Keke

HDU6521 Party

题意:有n个人,开m次派对,每次派对每对人会相互认识对方。对于每一次派对,我们要求出新认识的pair的数量。

 

 

 

你可能感兴趣的:(Algorithm)