Codeforces 420

A

Problem description

有k个物品和v个隔板,每个箱子最多分成b个空格,每个空格里最多放a个物品,求放下所有物品最少要多少箱子.

Data Limit2 ≤ k ≤ 1000; 1 ≤ a, b, v ≤ 1000 Time Limit: 1s

Solution

虽说可以O(1)出解,但比较麻烦容易错,反正数据小,为了正确性就模拟一下,考虑每个箱子,隔成最多的空格然后放最多的物品.

Code

#include<cstdio>
int n,k,t,a,b,v,ans=0;
int min(int x,int y)
{
    if (x>y)return y;else return x;
}
int main()
{
    scanf("%d%d%d%d",&k,&a,&b,&v);
    while (a>0)
    {
        ans++;
        t=min(b,k-1);b-=t;
        if(a<=(t+1)*v)
        {
            printf("%d",ans);
            return 0;
        }
        a-=(t+1)*v;
    }
    return 0;
}

 

B

Problem description

给出n和n棵树的高度a以及等差k,修建最少的树使n棵树的高度为等差为k的等差数列(修建可以使树增高,但不能修成负数)

Data Limit:1 ≤ n, k ≤ 1000 1 ≤ ai ≤ 1000 Time Limit: 1s

Solution

由于是等差数列,所以枚举第一棵树的高度就可以啦,还可以避免出现负数.

Code

#include<cstdio>
int n,i,j,a[10000],k,t=0,min=1e8,mini;
int main()
{
    scanf("%d%d",&n,&k);
    for (i=1;i<=n;i++)scanf("%d",&a[i]);
    for (i=1;i<=10000;i++)
    {
        t=0;
        for (j=1;j<=n;j++)
        if (i+(j-1)*k!=a[j])t++;
        if (t<min)
        {
            min=t;mini=i;
        }
        
    }
    printf("%d\n",min);
    for (i=1;i<=n;i++)
    if (a[i]!=mini+(i-1)*k)
    {
        if (a[i]>mini+(i-1)*k)printf("- %d %d\n",i,a[i]-mini-(i-1)*k);
        if (a[i]<mini+(i-1)*k)printf("+ %d %d\n",i,-a[i]+mini+(i-1)*k);
    }
    return 0;
}

C

Problem description

给出一个只有正数和0的边长为n的方形矩阵a,若有a^k全是正数,则打yes,否则打出no(k为任意自然数)

Data Limit:n <=2000  Time Limit: 1s

Solution

由题意,可以把原矩阵看做邻接矩阵,然后只要判断原图是否联通就好了.

Code

#include<cstdio>
int n,i,j,k=0;
int a[6000][6000];
bool bo[10000000],ans;


void dfs1(int x)
{
    if (bo[x])return;
    bo[x]=true;
    for (int i=1;i<=n;i++)if (a[i][x]>0)dfs1(i);
    return;
}
void dfs2(int x)
{
    if (bo[x])return;
    bo[x]=true;
    for (int i=1;i<=n;i++)if (a[x][i]>0)dfs2(i);
    return;
}
int main()
{
    scanf("%d",&n);
    for (i=1;i<=n;i++)
    for (j=1;j<=n;j++)
    {
        scanf("%d",&a[i][j]);
        //if (a[i][j]>0&&i!=j)
        //add(i,j);
    }
    /*for (i=1;i<=n;i++)
    {
        h=0,t=0;
        for (j=1;j<=n;j++)bo[j]=false;
        dfs(i);
        for (j=1;j<=n;j++)if (!bo[j])
        {
            puts("NO");
            return 0;
        }
    }*/
    ans=true;
    dfs1(1);
    for (i=1;i<=n;i++)
    {
        ans&=bo[i];
        bo[i]=false;
    }
    dfs2(1);
    for (i=1;i<=n;i++)
    {
        ans&=bo[i];
        bo[i]=false;
    }
    if (ans)puts("YES");else puts("NO");
    return 0;
}

E

Problem description

给出一个数列,和m个坏指数,进行几次修改,使所有数的f()值之和最大. 修改:取一个数r,将1到r的数全除以其最大公约数. f():f(1)=0,其他的将原数分解质因数后好质数数-坏质数数=其f值.

Data Limit:1 ≤ n, m ≤ 5000 Time Limit: 1s

Solution

从后向前扫,如果在某处修改后对答案有利,就修改,否则不改.

Code

#include<cstdio>
int n,m,i,j;
long long a[10000],b[10000],g[10000],top=0,p[1000000],minii,ans=0,mini,ff[20000000],hhh;
bool bo[10000000],booo;
long long gcd(long long a,long long b)
{
    if (b>a)return gcd(b,a);
    if (b==0)return a;else return gcd(b,a%b);
}
long long f(long long x)
{
    int ttt=x;
    if (x==1)return 0;
    if (x<10000000&&ff[x]!=0)return ff[x];
    long long ans=0,i,j;
    for (i=1;i<=m;i++)
    if (x>=b[i])
    while (x%b[i]==0)
    {
        ans--;
        x=x/b[i];
        if (x<10000000&&ff[x]!=0)return ff[x]+ans;
    }
    for (i=1;i<=top;i++)
    if (x>=p[i])
    while (x%p[i]==0)
    {
        ans++;
        x=x/p[i];
        if (x<10000000&&ff[x]!=0)return ff[x]+ans;
    }
    if (x!=1)ans++;
    if (ttt<10000000)ff[ttt]=ans;
    return ans;
    
}
int main()
{
    scanf("%d%d",&n,&m);
    for (i=1;i<=n;i++)scanf("%d",&i[a]);
    for (i=1;i<=m;i++)scanf("%d",&b[i]);g[1]=a[1];
    for (i=2;i<=n;i++)g[i]=gcd(g[i-1],a[i]);
    for (i=2;i<=100000;i++)
    if (!bo[i])
    {
        bo[i]=true;
        for (j=2;j<=100000;j++)
        if (i*j>100000)break;else bo[i*j]=true;
        booo=false;
        for (j=1;j<=m;j++)
        {
            if (i==b[j])booo=true;
        }
        if (!booo)
        {
            top++;
            p[top]=i;
        }
    }
    int div=1;
    for (i=n;i>=1;i--)
    {
        int tmp=f(g[i]/div);
        if(tmp<0) div = g[i];
        a[i] /= div; 
    }
    for (i=1;i<=n;i++)
    ans+=f(a[i]);
    printf("%d",ans);
    return 0;
}

 

F

Problem description

给出n和p,构造一个无向图,它有2n+p条边,n个点,无重边自环,且每个有k个点的字图中最多有2k+p个点.

Data Limit:5 ≤ n ≤ 24; p ≥ 0 Time Limit: 1s

Solution

比赛时面向样例编程,然后过了...... 那怎么证明这是对的呢? 暂时不知道...

Code

#include<cstdio>
int n,i,j,p,a,b,T;
int main()
{
    scanf("%d",&T);
    while (T--)
    {
    scanf("%d%d",&n,&p);a=1;b=2;
    for (i=1;i<=2*n+p;i++)
    {
        printf("%d %d\n",a,b);
        if (b<n)b++;else 
        {
            a++;b=a+1;
        }
    }
}
    return 0;
}

 

 

 

 

posted @ 2017-09-03 19:21  橙子用户  阅读(178)  评论(0编辑  收藏  举报