2016广东工业大学新生杯决赛网络同步赛暨全国新生邀请赛 几个写出来了的题目

2016广东工业大学新生杯决赛网络同步赛暨全国新生邀请赛
几个写出来了的题目
A.
`#include

#include<stdio.h>


int main(void)
{
    long long t,i,j,k,ans,w,s;
    long long n;
    scanf("%lld",&t);
    for (k=1;k<=t;k++)
    {
        scanf("%lld",&n);
        ans=0;
        while(n)
        {
            n/=2;
            ans+=n;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

其实和A题一样,但比赛时想了很久…
n!=1*2*3*…..*n,其中有2的因子的有2,4,6…..,数量为n/2。
取出这些数然后/2,便形成了新的序列1,2,3,4…..,即缩小了问题的规模。
所以只要重复操作即可。

C.

#include<stdio.h>
long long dp[10000];

int min(int a, int b)
{
    if (a>b) return b;
    else return a;
}

int main(void)
{
    int n, a, b, c, t, i, j, k, yu, ans;
    scanf("%d", &t);
    for (k = 1;k <= t;k++)
    {
        scanf("%d %d %d %d", &n, &a, &b, &c);
        if (n % 4 == 0)
        {
            printf("%d\n", 0);
            continue;
        }
        dp[1] = a;
        dp[2] = min(2 * a, b);
        dp[3] = min(min(dp[2] + dp[1], dp[1] * 3), c);
        yu = 4 - n % 4; ans = dp[yu];
        for (i = 4;i <= 30;i++)
        {
            dp[i] = min(min(dp[i - 1] + a, dp[i - 2] + dp[2]), dp[i - 3] + dp[3]);
            if (dp[i]<ans && i % 4 == yu) ans = dp[i];
        }
        printf("%d\n", ans);
    }
    return 0;
}

动态规划.dp[i]存放买i本书所需的最小花费。
所以状态转移方程dp[i]=min(dp[i-3]+dp[3],min(dp[i-1]+dp[1],dp[i-2]+dp[2]))
其中dp[1]=a(只有1种买法)
dp[2]=min(a*2,b)(买2个1本或1个2本)
dp[3]=min(c,min(a*3,dp[2]+a))(3个1本,1个1本+1个2本,1个3本)
需要购买的数量为(4-n%4)+4*k本(k为任意自然数)
我的想法:需要买的本数最多的情况是全买1次3本的直到够分,所以dp算到15。
实际上,只有更少的情况:
对于余数为1的情况:买1个1本 ,或者买1个2本+1个3本,或者买3个3本
(a,b,c大于0,不确定的只有这三个数之间的大小关系.其他情况都比这三种情况大)
对于余数为2的情况:买1个2本,或者买2个1本,或者买2个3本
(对于买1个1本1个3本,必定在a+a和c+c之间,所以不予考虑)
对于余数为3的情况:买1个3本,或者买3个1本,或者买1个2本1个1本。

另外:虽然n,a,b,c在1e9以内,但因为涉及到3*a,所以会超出int范围
(我就是因为这个始终没有想明白为什么wrong answer….)

F.

#include<stdio.h>
#include<string.h>

int main(void)
{
    printf("ac");
    return 0;
}
水题

G.

#include<stdio.h>

int main(void)
{
    int n,k,i,j,z,x;
    while (scanf("%d %d",&n,&k)!=EOF)
    {
        z=1; x=1;
        for (i=n;i>=n-k+1;i--) z=z*i;
        for (i=k;i>=2;i--) x=x*i;
        if (x==0) z=1;
           else z=z/x;
        printf("%d\n",z);
    }
    return 0;
}

水题.求组合数

I.

#include<stdio.h>
struct zt
{
    int left;
    int right;
    int up;
    int down;
};

int ans;
int n, m;
struct zt tu[1010][1010] = { 0 };

void solve(int x, int y)
{
    if (ans == 1) return;
    if (x == n && y == m)
    {
        printf("Well done!\n");
        ans = 1;
    }
    if (tu[x][y].right == 1 && tu[x][y + 1].left == 1)
        solve(x, y + 1);
    if (tu[x][y].down == 1 && tu[x + 1][y].up == 1)
        solve(x + 1, y);
    return;
}



int main(void)
{
    int t, i, j, k, x, y;
    char v, b,l;
    scanf("%d", &t);
    for (i = 1;i <= t;i++)
    {
        scanf("%d %d", &n, &m);
        for (i = 1;i <= n;i++)
            for (j = 1;j <= m;j++)
            {
                tu[i][j].left = 0;
                tu[i][j].right = 0;
                tu[i][j].up = 0;
                tu[i][j].down = 0;
            }

        for (i = 1;i <= n;i++)
        {
            getchar();
            for (j = 1;j <= m;j++)
            {
                scanf("%c%d%c%d%c", &v, &x, &l, &y, &b);
                switch (x)
                {
                case 3:
                    switch (y)
                    {
                    case 0:
                        tu[i][j].left = 1;
                        tu[i][j].right = 1;
                        tu[i][j].down = 1;
                        break;
                    case 1:
                        tu[i][j].up = 1;
                        tu[i][j].left = 1;
                        tu[i][j].down = 1;
                        break;
                    case 2:
                        tu[i][j].up = 1;
                        tu[i][j].left = 1;
                        tu[i][j].right = 1;
                        break;
                    default:
                        tu[i][j].up = 1;
                        tu[i][j].right = 1;
                        tu[i][j].down = 1;
                        break;
                    }
                    break;
                case 4:
                    tu[i][j].up = 1;
                    tu[i][j].down = 1;
                    tu[i][j].right = 1;
                    tu[i][j].left = 1;
                    break;
                case 0:
                    break;
                default:
                    switch (y)
                    {
                    case 0:
                        tu[i][j].left = 1;
                        tu[i][j].right = 1;
                        break;
                    case 1:
                        tu[i][j].up = 1;
                        tu[i][j].down = 1;
                        break;
                    case 2:
                        tu[i][j].left = 1;
                        tu[i][j].down = 1;
                        break;
                    case 3:
                        tu[i][j].up = 1;
                        tu[i][j].right = 1;
                        break;
                    case 4:
                        tu[i][j].up = 1;
                        tu[i][j].left = 1;
                        break;
                    case 5:
                        tu[i][j].down = 1;
                        tu[i][j].right = 1;
                        break;
                    }
                    break;
                }
            }
        }
        ans = 0;
        solve(1, 1);
        if (ans == 0)
            printf("What a pity!\n");
    }
    return 0;
}

深度优先搜索,若向右或下走得通(该点的右边(下边)有路,且目标点的左边(上边)有路),那么就去尝试.找到一条路径后退出。

J.

#include<stdio.h>
#include<math.h>
int main(void)
{
    int t,n,i,j,k,find,x,left,right;
    scanf("%d",&t);
    for (k=1;k<=t;k++)
    {
        scanf("%d",&n);
        find=1; x=n;
        while (find)
        {
            int m=sqrt(x);
            if (sqrt(x)*sqrt(x)==x)
            {

                for (i=2;i<=sqrt(m);i++)
                {
                    if (m%i==0) break;
                }

            if (i>sqrt(m)) {find=0; right=x;}
            }
            if (find==1) x++;
        }
        find=1;
        x=n-1;
        while (find && x>1)
        {
            int m=sqrt(x);
            if (sqrt(x)*sqrt(x)==x)
            {

                for (i=2;i<=sqrt(m);i++)
                {
                    if (m%i==0) break;
                }

            if (i>sqrt(m)) {find=0; left=x;}
            }
            if (find==1) x--;
        }
        if (find==1) printf("%d\n",right);
        else if (right-n<n-left) printf("%d\n",right);
        else printf("%d\n",left);

    }
    return 0;
}

分别向后搜索、向前搜索,先判断是否为平方数,再取平方根进行素数判断,最后取距离小的。

总之,作为一个新生,还是有很多需要改进的地方。程序只作参考,不一定是简单的思路。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值