国庆七天乐 Day7

今天做的是湖南省2010年省赛题,悲催的只出了四题...今年省赛堪忧!

先做Codeforce去了...

A:汽水瓶

有这样一道智力题:“某商店规定:三个空汽水瓶可以换一瓶汽水。小张手上有十个空汽水瓶,她最多可
以换多少瓶汽水喝?”答案是5瓶,方法如下:先用9个空瓶子换3瓶汽水,喝掉3瓶满的,喝完以后4个空瓶
子,用3个再换一瓶,喝掉这瓶满的,这时候剩2个空瓶子。然后你让老板先借给你一瓶汽水,喝掉这瓶满
的,喝完以后用3个空瓶子换一瓶满的还给老板。如果小张手上有n个空汽水瓶,最多可以换多少瓶汽水喝?

推算一下会发现最后的答案是n/2。

#include <stdio.h>

int main()
{
    //freopen("a.in", "r", stdin);
    //freopen("A.out", "w", stdout);
    int n;
    while(scanf("%d", &n), n)
    {
        printf("%d\n", n / 2);
    }
    return 0;
}

B:弟弟的作业

你的弟弟刚做完了“100以内数的加减法”这部分的作业,请你帮他检查一下。每道题目(包括弟弟的答案)
的格式为a+b=c或者a-b=c,其中a和b是作业中给出的,均为不超过100的非负整数;c是弟弟算出的答案,
可能是不超过200的非负整数,也可能是单个字符"?",表示他不会算。输出答对的数目

巨水的一道题,我居然小卡了一下!!!看到标程后表示跪了!

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char s1, s2, s5[5];
int a, b, c;
char s[20];
int main()
{
    int cnt = 0;
    while(scanf("%d%c%d%c%s", &a, &s1, &b, &s2, s5) != EOF)
    {
        if(s5[0] == '?') continue;
        int t = 1;
        c = 0;
        for(int i = strlen(s5) - 1; i >= 0; i --)
        {
            c += t * (s5[i] - '0');
            t *= 10;
        }
        if(s1 == '-')
        {
            if(a - b == c)
                cnt ++;
        }
        if(s1 == '+')
        {
            if(a + b == c)
                cnt ++;
        }
    }
    printf("%d\n", cnt);
    return 0;
}

标程:

#include<stdio.h>
int main() {
  char s[99];
  int a, b, c, n = 0;
  while(scanf("%s", &s) == 1) {
    if(sscanf(s, "%d+%d=%d", &a, &b, &c) == 3 && a+b==c) n++;
    if(sscanf(s, "%d-%d=%d", &a, &b, &c) == 3 && a-b==c) n++;
  }
  printf("%d\n", n);
  return 0;
}

不愧是刘汝佳大神啊!

C:数字整除

定理:把一个至少两位的正整数的个位数字去掉,再从余下的数中减去个位数的5倍。当且仅当差是17的
倍数时,原数也是17的倍数。

输入一个10^100次方以内的数,判断能不能被17整除。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
const int MAXN = 110;
char str[MAXN];

int main()
{
    while(scanf("%s", &str) != EOF)
    {
        if(str[0] == '0') break;
        int ret;
        int len = strlen(str);
        if(len == 1)
        {
            int d = str[len - 1] - '0';
            if(d % 17) puts("0");
            else puts("1");
            continue;
        }
        else if(len == 2)
        {
            int d = str[1] - '0' + 10 * (str[0] - '0');
            if(d % 17) puts("0");
            else puts("1");
            continue;
        }
        int i;
        for(i = len - 1; i >= 2;)
        {
            int d = str[i] - '0';
            int t = 0;
            t += (str[i - 1] - '0');
            t += (str[i - 2] - '0') * 10;
            while(t < d * 5)
            {
                t += 17;
            }
            t -= 5 * d;
            str[i - 2] = t / 10 + '0';
            str[i - 1] = t % 10 + '0';
            i --;
        }
        int d = str[1] - '0' + 10 * (str[0] - '0');
        if(d % 17) puts("0");
        else puts("1");
    }
    return 0;
}

标程又深深打击了我:

#include<stdio.h>
#include<string.h>
int main() {
  char s[200];
  while(scanf("%s", &s) == 1) {
    if(!strcmp(s, "0")) break;
    int m = 0;
    for(int i = 0; i < strlen(s); i++)
      m = (m*10+s[i]-'0')%17;
    printf("%d\n", m==0?1:0);
  }
  return 0;
}

D:台球碰撞

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
double L, W, x, y, R, a, v, s;
const double PI = asin(1) * 2;

int main()
{
    freopen("d.in", "r", stdin);
    freopen("D.out", "w", stdout);
    while(scanf("%lf%lf%lf%lf%lf%lf%lf%lf", &L, &W, &x, &y, &R, &a, &v, &s) != EOF)
    {
        if(L + W + x + y + R + a + v + s < 1e-8) break;
        L -= (2 * R), W -= (2 * R), x -= R, y -= R;
        double sum = v * s;
        double dx = cos(a / 180.0 * PI) * sum;
        double dy = sin(a / 180.0 * PI) * sum;

        dx = fmod(fmod(dx, L * 2) + L * 2, L * 2);
        dy = fmod(fmod(dy, W * 2) + W * 2, W * 2);
        dx += x, dy += y;
        if(dx <= L);
        else if(dx <= L * 2) dx = 2 * L - dx;
        else dx -= 2 * L;
        if(dy <= W);
        else if(dy <= W * 2) dy = 2 * W - dy;
        else dy -= 2 * W;

        printf("%.2f %.2f\n", dx + R, dy + R);
    }
    return 0;
}

E:内部收益率

解这个方程求IRR,二分就可以了,比赛的时候一点都没想到,我真弱!我推出来的IRR的范围大致是-1到100之间,因为数据比较小,拍过了!

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

int n, a[15];
int main()
{
    freopen("e.in", "r", stdin);
    freopen("es.out", "w", stdout);
    while(scanf("%d", &n), n)
    {
        for(int i = 0; i <= n; i ++)
        {
            scanf("%d", &a[i]);
        }
        double l = -1.0, r = 100, m;
        for(int i = 0; i < 100; i ++)
        {
            m = l + (r - l) / 2;
            double x = 1.0, sum = 0.0;
            for(int j = 1; j <= n; j ++)
            {
                x /= (1 + m);
                sum += a[j] * x;
            }
            if(sum < -a[0]) r = m;
            else l = m;
        }
        printf("%.2f\n", m);
    }
    return 0;
}

F:

G Repairing a Road

这道题如果没有修一条路这个条件就是普通的单源最短路径的题,直接上dijkstra就能解决。但是加上了修路这个条件之后题目就变难了不少。大致题意是这样,

无向图, C个点,R条边,每条边连接两个点u,v,修路之前通过这条边的时间是vt,被修过的路通过的时间就变成了vt * at的-t次方,每条边的at都是给定的,

t为这条路被修的时间,这里也是本题的难点,你从离开源点1就可以叫你的朋友修路, 修路过程中不可以通过,但是假如你到了a点,你可以选择在a点等待时间t1然

后通过,此时修路的时间是t + t1,你经过这条边的时间就是t1 + vt * at的-(t + t1)次方,这里让我不知道怎么做。而且我的主体思路有问题,我先用dij做了

一遍最短路,然后从枚举每条边,假设起点是i,这里t就是d[1][i],在求一个t使得通过该条边的时间最短,看上去貌似没什么错误,但是每次枚举一条边都得做一次

最短路,而且最终结果还不对。正解是floyd求一遍任意两点间的最短路,然后枚举两点i,j,两点如果存在vt的话,证明他们之间有一条边,这样从1到C的最短路就

是d[1][i] + d[j][C] + 通过这条边的时间,前面两个是定值了,然后t=d[1][i]无误,求t1或者说求通过这条边的时间用了逼近最小值的方法,这里之前不会,不过

好在现在会了。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <algorithm>
using namespace std;
const int MAXR = 550;
const int MAXN = 110;
const double eps = 1e-6;
const double INF = 10000000.0;
int C, R;
double d[MAXN][MAXN], vt[MAXN][MAXN], at[MAXN][MAXN];

void ReadGraph()
{
    for(int i = 1; i <= C; i ++)
    {
        for(int j = 1; j <= C; j ++)
        {
            if(i != j)
                d[i][j] = INF;
            else
                d[i][j] = 0.0;
            vt[i][j] = INF;
        }
    }
    while(R --)
    {
        int a, b;
        double vc, ac;
        scanf("%d%d%lf%lf", &a, &b, &vc, &ac);
        d[a][b] = d[b][a] = vc;
        vt[a][b] = vt[b][a] = vc;
        at[a][b] = at[b][a] = ac;
    }
}

void floyd()
{
    for(int k = 1; k <= C; k ++)
        for(int i = 1; i <= C; i ++)
            for(int j = 1; j <= C; j ++)
                d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}

double calc()
{
    double ans = d[1][C];
    for(int i = 1; i <= C; i ++)
    {
        for(int j = 1; j <= C; j ++)
        {
            if(i == j || vt[i][j] == INF) continue;
            double low = 0.0, high = 10.0;
            double t = d[1][i];
            while(high - low > eps)
            {
                double l = (2.0 * low + high) / 3.0;
                double r = (2.0 * high + low) / 3.0;
                //逐渐接近最小值
                double res1 = l + vt[i][j] * pow(at[i][j], -(l + t));
                double res2 = r + vt[i][j] * pow(at[i][j], -(t + r));

                if(res1 < res2)
                    high = r;
                else low = l;
                ans = min(ans, min(res1, res2) + d[1][i] + d[j][C]);
            }
        }
    }
    return ans;
}

int main()
{
    while(scanf("%d%d", &C, &R), C + R)
    {
        ReadGraph();
        floyd();
        printf("%.3f\n", calc());
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/Yu2012/archive/2012/10/07/2714634.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值