您的位置:首页 > 理论基础 > 计算机网络

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

2016-12-04 23:41 417 查看
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
4000
== 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;
}


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

总之,作为一个新生,还是有很多需要改进的地方。程序只作参考,不一定是简单的思路。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  广工大新生杯 2016
相关文章推荐