HDU多校十

总结:
最后一场多校,队内对待很认真,讨论也挺激烈的,但是还有由于有BUG没有解决所以没过。

1011

题意

有nn个任务,mm个工人,其中kk个工人不能用,每个任务需要aiai个工人,且必须是可用的工人,每次任务随机选aiai个工人,如果有不可用的工人,则会重新进行选择,输出你安排任务的选择顺序,使得选择的期望最小。包装m−km−k个工人可以完成nn个任务。

思路

对输入进行下标排序

代码

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct aaa{
    int val;
    int num;
};
bool cmp(aaa a,aaa b)
{
    if(a.val!=b.val)
    return a.val>b.val;
    else
    return a.num<b.num;
}

aaa a[10005];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m,k;
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i].val);
            a[i].num=i;
        }
        if(k!=0)
        sort(a+1,a+n+1,cmp);
        for(int i=1;i<=n;i++)
        {
        	if(i!=n)
        	printf("%d ",a[i].num);
        	else
        	printf("%d",a[i].num);
		 } 
        
        printf("\n");     
    }
    return 0;
}

1003

题意

扫雷地图可以表示为r×c网格,每个网格单元都是mine单元或非mine单元。一个矿细胞上没有数字,而一个非矿细胞有一个数字,即与该细胞至少有一个共同点的矿细胞的数量。以下是一个16×30个扫雷车地图,其中标志单元格表示地雷单元格,空白单元格表示非地雷单元格,数字为0。
给定一个整数S,绘制一张扫雷地图r、c它们都不超过25个,它们在非地雷细胞上的总数正好相等S。如果存在多个解决方案,请打印其中任何一个。如果没有解决方案,请在一行中打印“-1”。
对于每个测试用例如果没有解决方案,请在一行中打印“-1”。
如果存在任何解,则打印两个整数r、c(1≤r,c≤25)在第一行,表示扫雷车地图的大小。跟随r每行包含一个只包含“.”或“X”长度的字符串c,其中“.”、“X”分别表示非地雷单元和地雷单元,表示您构建的扫雷器地图的每一行。
请注意,您不必在非地雷单元上打印数字,因为这些数字可以由输出扫雷器地图确定。

思路

一个九宫格,中间位置为“.”,其余八个位置为“X”,的地图贡献一个8的贡献。只需要在25*25的“X”矩阵里全放这样的结构即可。多出来的格子,格子数量最多为7个,在矩阵中分布即可。如果n小于等于24,可以构造这样的地图“.X.X.……”,可知长度为len的时候,数字和等于len-1。

代码

#include<bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false),cin.tie(0);
#define ll long long
#define inf 0x3f3f3f3f
const int N=55;
//set<string>b;
//set<string>::iterator it;
ll vis[N][N];
int main()
{
	IO;
	int T;
	ll n,i,j,len,x;
	double sum;
	cin>>T;
	while(T--)
	{
		memset(vis,0,sizeof(vis)); 
		cin>>n;
		if(n<25)
		{
			cout<<"1 "<<n+1<<endl;
			for(i=1;i<=n+1;i++)
			{
				if(i%2) cout<<"X";
				else cout<<".";
			}
			cout<<endl;
			continue;
		}
		sum=n/8;
		len=sum/12;
		x=n%8;
		cout<<"25 25\n";
		for(i=1;i<=len;i++)
		{
			for(j=1;j<=12;j++)
			{
				vis[i*2][j*2]=1;
			}
		}
		if(len*12<sum)
		{
			int cnt=sum-len*12;
			for(i=1;i<=cnt;i++)
			{
				vis[len*2+2][2*i]=1;
			}
		}
		if(x==1) vis[1][1]=1;
		else if(x==2) vis[1][1]=vis[1][2]=1;
		else if(x==3) vis[25][1]=1;
		else if(x==4) vis[1][1]=vis[25][1]=1;
		else if(x==5) vis[25][2]=1;
		else if(x==6) vis[25][25]=vis[25][1]=1;
		else if(x==7) vis[1][1]=vis[25][25]=vis[25][1]=1;
		for(i=1;i<=25;i++)
		{
			for(j=1;j<=25;j++)
			{
				if(vis[i][j]) cout<<".";
				else cout<<"X";
			}
			cout<<endl;
		}
	}
    return 0;
}

1004

题意

给你一个n和k。问你有多少种数字序列满足有k个数字比该数字对应的下标大。

思路

dp[i][j]表示用到1-i的数字。且有j个数字比下标大的方法数。那么dp[i][j]=(j+1)*dp[i-1][j]+(i-j)*dp[i-1][j-1]。

代码

#include <bits/stdc++.h>
#define ll long long
#define PII pair<int,int>
#define ls x<<1
#define rs x<<1|1
#define fi first
#define se second
#define pb push_back
#define inf 0x3f3f3f3f
using namespace std;
const int N=5e6+10;
#define MOD 1000000007
__int64 p[1001][1001];
int main()
{
    int i,j,n,k;
    for(i = 1;i <= 1000;i ++)
    {
        p[i][0] = 1;
        p[i][i-1] = 1;
    }
    for(i = 3;i <= 1000;i ++)
    {
        for(j = 1;j <= (i+1)/2-1;j ++)
        {
             p[i][i-1-j] = p[i][j] = (((i-j)*p[i-1][j-1])%MOD+((j+1)*p[i-1][j])%MOD)%MOD;
        }
    }
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        printf("%I64d\n",p[n][k]);
    }
    return 0;
}

一级目录

题意

思路

代码

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页