Codeforces Round #277.5 (Div. 2)

A

题意:给定n个数,最多交换n次获得一个不减的序列,求一个合法的交换序列。

题解:每次找从i开始的最小值换到第i个位置就可以了。

#include <cstdio>

#include <algorithm>

#include <cstring>

#include <iostream>

#include <cmath>

using namespace std;

int a[5000],n,max1,maxx;

int main()

{

    scanf("%d",&n);

    for (int i=1;i<=n;++i) scanf("%d",&a[i]);

    printf("%d\n",n);

    for (int i=1;i<=n;++i)

    {

        max1=2e9;maxx=0;max1=-max1;

        for(int j=1;j<=n-i+1;++j) if (a[j]>max1)

        {

            max1=a[j];maxx=j;

        }

        swap(a[maxx],a[n-i+1]);

        printf("%d %d\n",maxx-1,n-i);

    }

    return 0;

}

B

题意:N个男孩M个女孩参加舞会,每个人有一个能力值,两个跳舞的人必须为一男一女且能力值差在1之内,求最多有多少对。

题解:直接求个匹配就可以了。。

#include <cstdio>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <cstring>
int num,b[200],a[20000],next[20000],a1[200],a2[200],ans,vis[200],n,m,link[200];
using namespace std;
int dfs(int x)
{
    for (int i=b[x];i;i=next[i])
    {
        int y=a[i];
        if (!vis[y])
        {
            vis[y]=1;
            if (link[y]==0||dfs(link[y]))
            {
                link[y]=x;
                return 1;
            }
        }
    }
    return 0;
}
void addedge(int x,int y)
{
    ++num;a[num]=y;next[num]=b[x];b[x]=num;
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;++i) scanf("%d",&a1[i]);
    scanf("%d",&m);
    for (int j=1;j<=m;++j) scanf("%d",&a2[j]);
    for (int i=1;i<=n;++i)
        for (int j=1;j<=m;++j) if (abs(a1[i]-a2[j])<=1) addedge(i,j);
    //cout<<num;
    for (int i=1;i<=n;++i)
    {
        memset(vis,0,sizeof(vis));
        if (dfs(i)) ans++;
    }
    printf("%d\n",ans);
    return 0;
}

C

题意:求最大的和最小的N位数,使得这个N位数各个位数字的和为M。

题解:最大的从前往后一直放9到不能放为止。。最小的从前往后每一位都放能放的最小值。。

#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;
int m,s,ss;
int a[1000],b[1000];
int main()
{
    scanf("%d%d",&m,&s);
    ss=s;
    if (s>m*9)
    {
        printf("-1 -1\n");
        return 0;
    }
    if (m==1)
    {
        printf("%d %d\n",s,s);
        return 0;
    }
    if (s==0)
    {
        printf("-1 -1\n");
        return 0;
    }
    memset(a,0,sizeof(a));
    memset(b,0,sizeof(b));
    for (int i=1;i<=m;++i)
    {
        if (i==1) a[i]=max(1,s-(m-i)*9);else a[i]=max(0,s-(m-i)*9);s-=a[i];
    }
    s=ss;
    for (int i=1;i<=m;++i)
    {
        if (s<=9) b[i]=s;else b[i]=9;s-=b[i];
        if (s==0) break;
    }
    for (int i=1;i<=m;++i) printf("%d",a[i]);
    printf(" ");
    for (int i=1;i<=m;++i) printf("%d",b[i]);
    return 0;
}

D

题意:给一个N个点M条边的图,问存在多少个这样的四元组(a,b,c,d) 使得a到b有边 a到d有边 b到c有边 d到c有边。

题解:枚举每一个点作为a,然后把a能到的每个点能到的d的次数统计出来,记为sum[d] 则对于a答案为sigma(c(sum[d],2)) 求和即可。

#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
vector<int> a[3005];
int n,m,x,y;
long long ans,flag[3005];
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;++i)
    {
        scanf("%d%d",&x,&y);
        a[x].push_back(y);
    }
    for (int i=1;i<=n;++i)
    {
        memset(flag,0,sizeof(flag));
        for (int j=0;j<a[i].size();++j)
        {
            for (int k=0;k<a[a[i][j]].size();++k) flag[a[a[i][j]][k]]++;
        }
        for (int j=1;j<=n;++j)
        {
            if (j==i) continue;
            if (flag[j]<2) continue;
            ans+=flag[j]*(flag[j]-1)/2;
        }
    }
    printf("%I64d",ans);
    return 0;
}

F

题意:一个N*N的0 1矩阵 要求每个矩阵元素不是0就是1 现在要求每行每列都恰好有两个1,若前m行已给出,求方案总数。

题解:记忆化搜索:

  DP[A,B]表示还剩下A列需要1个1,B列需要2个1,这时候对应的行数也就能知道了。

  考虑转移:DP[A,B]有三种情况:两个都填在需要1个1的列 此时答案为c(A,2)*DP[A-2,B]

                 两个都填在需要2个1的列 此时答案为c(B,2)*DP[A+2,B-2]

                 一个填在需要1个1的列,一个填在需要2个的列 此时答案为 A*B*DP[A,B-1]

       边界DP[0][0]=1 直接记忆化搜索即可。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
typedef long long LL;
using namespace std;
int n,k;
int a[505],sum1,sum2;
LL dp[505][505],m,ans,map[505][505];
char ch[505];
LL dfs(int x,int y)
{
    if (map[x][y]!=0) return dp[x][y];
    dp[x][y]=0;map[x][y]=1;
    if (x==0&&y==0)
    {
        dp[x][y]=1;
        return 1;
    }
    if (y>=2) dp[x][y]=(dp[x][y]+dfs(x+2,y-2)*y*(y-1)/2)%m;
    if (x>=2) dp[x][y]=(dp[x][y]+dfs(x-2,y)*x*(x-1)/2)%m;
    if (x>=1&&y>=1) dp[x][y]=(dp[x][y]+dfs(x,y-1)*x*y)%m;
    return dp[x][y];
}
int main()
{
    memset(map,0,sizeof(map));
    memset(dp,0,sizeof(dp));
    scanf("%d%d%I64d",&n,&k,&m);
    for (int i=0;i<n;++i) a[i]=2;
    for (int i=1;i<=k;++i)
    {
        scanf("%s",ch);
        for (int j=0;j<n;++j) if (ch[j]==‘1‘) a[j]--;
    }
    sum1=0;sum2=0;
    for (int i=0;i<n;++i) if (a[i]==1) sum1++;
    for (int i=0;i<n;++i) if (a[i]==2) sum2++;
    ans=dfs(sum1,sum2);
    printf("%I64d\n",ans);
    return 0;
}
时间: 2024-10-12 13:53:14

Codeforces Round #277.5 (Div. 2)的相关文章

Codeforces Round #277.5 (Div. 2) JAVA版题解

Codeforces Round #277.5 (Div. 2) A. SwapSort time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output In this problem your goal is to sort an array consisting of n integers in at most n swaps. For t

Codeforces Round #277.5 (Div. 2) b

/**  * @brief Codeforces Round #277.5 (Div. 2) b  * @file b.c  * @author 面码  * @created 2014/11/18 17:22  * @edited  2014/11/18 17:22  * @type greedy  *  */ #include <stdio.h> #define MAXN 110 #define max(a, b)  ((a) > (b) ? (a) : (b)) #define mi

Codeforces Round #277.5 (Div. 2)C. Given Length and Sum of Digits...(贪心)

传送门 Description You have a positive integer m and a non-negative integer s. Your task is to find the smallest and the largest of the numbers that have length m and sum of digits s. The required numbers should be non-negative integers written in the d

Codeforces Round #277.5 (Div. 2)D Unbearable Controversy of Being (暴力)

这道题我临场想到了枚举菱形的起点和终点,然后每次枚举起点指向的点,每个指向的点再枚举它指向的点看有没有能到终点的,有一条就把起点到终点的路径个数加1,最后ans+=C(路径总数,2).每两个点都这么弄.但是我考虑时间复杂度n2前面的系数过大会超时,再想别的方法也没想出来.. 其实思路就是这样的,只不过时间上可以优化一下,就是用常用的两种做法不变而优化时间复杂度的方法:1.以空间换时间2.分步降维 #include <cstdio> #include <vector> using n

Codeforces Round #277.5 (Div. 2)——C贪心—— Given Length and Sum of Digits

You have a positive integer m and a non-negative integer s. Your task is to find the smallest and the largest of the numbers that have length m and sum of digits s. The required numbers should be non-negative integers written in the decimal base with

Codeforces Round #277.5 (Div. 2)-D

题意:求该死的菱形数目.直接枚举两端的点.平均意义每一个点连接20条边,用邻接表暴力计算中间节点数目,那么中间节点任选两个与两端可组成的菱形数目有r*(r-1)/2. 代码: #include<iostream> #include<cstdio> #include<cmath> #include<map> #include<cstring> #include<algorithm> #define rep(i,a,b) for(int

Codeforces Round #277.5 (Div. 2) C Given Length and Sum of Digits...

大大的传送门:就是这里 这一道卡在了特判的  1   0 本来输出 0  0 输出  -1    -1了,就错了,, 这道题就是一个恨好的贪心,往大了贪 下面是代码 #include <cstdio> #include <cstring> #include <vector> using namespace std; int n,m; int ans[110]; int main(){ scanf("%d%d",&n,&m); mems

Codeforces Round #277.5 (Div. 2)-C

简单细节题: #include<iostream> #include<cstdio> #include<cmath> #include<map> #include<cstring> #include<algorithm> #define rep(i,a,b) for(int i=(a);i<(b);i++) #define rev(i,a,b) for(int i=(a);i>=(b);i--) #define clr(a

Codeforces Round #277.5 (Div. 2) 解题报告

还是只会4道..sad... A:SwapSort 用一个数组存储排好序之后.然后从头开始依次将需要交换的与本来应该在这个位置的交换,最多交换n-1次. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include <ctype.h>