2012icpc长春模拟

 

K 简单数学+二分..开始带偏了节奏tle 后来看错题wawawa...3人读题想清楚再写题的重要性

C 据说弄懂题意后分情况搞一搞 有点复杂但不难

 

B 隐藏深的枚举...整数当做32位01 分成32个矩阵分别判断 由于异或运算的唯一解性 数组只要有一个确定 就可以推出每一个元素 所以前2行的异或值可以确定每一个元素 其余值用来check是否可行 类似熄灯问题

题解大都写成2-sat问题..代码长度和用时远高于枚举.. 现场这么多过的 大都也是枚举吧

H dp..又以为是计数了搞一搞发现不可做...僵硬

 

E 给出一颗树 求一点到其他所有点的每条路径上最小权之和的最大值 并查集+贪心..实现就是排序然后依次加入并查集取max...难在想法..

J 读懂题目后 dfs建树 暴力求最近公共祖先 算法不是太难...转化比较难

 

D 题意明显的数学题..没什么算法高深的数学分析 就是很复杂

G 很难的字符串处理

 

可以说是有点坑的赛区..没有明显签到题 其他题也很耐想 铁牌区wa率很高...铜牌区2题 dp还好 枚举不大容易想到...银牌到金牌线智力题...金牌题是复杂数学分类分析和复杂字符串算法

简单题就看错题僵硬好久..铜牌题也没想法瞎搞...前4题get到点都很可做的...

EJ时间够的话也可以搏一搏

然而6题都有金了

 

 

补B代码:

#include <cstdio>

#include <cstring>

#include<cmath>

#include <algorithm>

using namespace std;

int a[505][505], b[505][505], x[505], n;

int ok(int q)

{

    int i, j;

    x[0] = q;

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

        x[i] = b[0][i] ^ x[0];

    for (i = 2; i < n; i += 2)

        x[i] = b[1][i] ^ x[1];

    for (i = 0; i < n; i++)

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

            if (i % 2 == 0 && j % 2 == 0 && b[i][j] != (x[i] & x[j]))

                return 0;

            else if (i % 2 && j % 2 && b[i][j] != (x[i] | x[j]))

                return 0;

            else if ((i + j) % 2 && b[i][j] != (x[i] ^ x[j]))

                return 0;

    return 1;

}

int main()

{

    int i, j, k, f;

    while (~scanf("%d", &n))

    {

        f = 0;

        for (i = 0; i < n; i++)

            for (j = 0; j < n; j++)

                scanf("%d", a[i] + j);

        for (i = 0; i < n; i++)

            for (j = 0; j < n; j++)

                if ((i == j&&a[i][j]) || a[i][j] != a[j][i])

                    f = 1;

        if (f) { puts("NO"); continue; }

        for (k = 0; k < 33; k++)

        {

            for (i = 0; i < n; i++)

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

                    b[i][j] = a[i][j] & 1, a[i][j] >>= 1;

            if (!ok(0) && !ok(1)) break;

        }

        puts(k == 33 ? "YES" : "NO");

    }

}

 

H 动态规划:(难点应该是优化时间 hash因子+滚动数组+预处理lcm zoj上不预处理lcm可过 hdu不可过..)
#include <cstdio>

#include <cstring>

#include<cmath>

#include <algorithm>

using namespace std;

#define mm 1000000007

int dp[1005][1005][2], a[1005], lcm[1005][1005];

int gcd(int x, int y)

{

    return y ? gcd(y, x%y) : x;

}

void init()

{

    int i, j;

    for (i = 1; i < 1005; i++)

        for (j = 1; j < 1005; j++)

            lcm[i][j] = i*j / gcd(i, j);

}

int main()

{

    int n, m, x, z, i, j, ii, jj, kk, k;

    init();

    while (~scanf("%d%d%d", &n, &m, &x))

    {

        z = 0;

        memset(dp, 0, sizeof(dp));

        for (i = 1; i <= m; i++)

            if (m%i == 0)

                a[z++] = i, dp[i][i][0] = 1;

        for (i = 1; i < x; i++)

        {

            for (j = i; j < n; j++)

                for (k = 0; k < z; k++)

                    if (dp[j][a[k]][0])

                        for (ii = 0; ii < z; ii++)

                        {

                            jj = j + a[ii], kk = lcm[a[k]][a[ii]];

                            if (jj <= n)

            dp[jj][kk][1] = (dp[j][a[k]][0] + dp[jj][kk][1]) % mm;

                        }

            for (j = 1; j <= n; j++)

                for (k = 0; k < z; k++)

                    dp[j][a[k]][0] = dp[j][a[k]][1], dp[j][a[k]][1] = 0;

 

        }

        printf("%d\n", dp[n][m][0]);

    }

}

 

E 注意答案上界是2*10^10 用longlong 判大小的时候相乘也要加1LL 在zoj因为这个wa一次 :

#include <cstdio>

#include <cstring>

#include <algorithm>

using namespace std;

struct node { int u, v, w; }a[200002];

int u[200002];

long long ans[200002], v;

int find(int x)

{

    if (u[x] < 0) return x;

    u[x] = find(u[x]);

    return u[x];

}

void mix(int x, int y)

{

    if ((x = find(x)) == (y = find(y))) return;

    if (u[x] < u[y])

        u[x] += u[y], u[y] = x;

    else

        u[y] += u[x], u[x] = y;

}

int cmp(node x, node y)

{

    return x.w > y.w;

}

int main()

{

    int n, i, x, y, z;

    while (~scanf("%d", &n))

    {

        memset(u, -1, sizeof(u)), memset(ans, 0, sizeof(ans));

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

            scanf("%d%d%d", &a[i].u, &a[i].v, &a[i].w);

        sort(a + 1, a + n, cmp);

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

        {

            x = find(a[i].u), y = find(a[i].v), z = a[i].w;

            v = max(ans[x] + 1LL * z*-u[y], ans[y] + 1LL * z*-u[x]);

            mix(a[i].u, a[i].v);

            ans[find(a[i].u)] = v;

        }

        printf("%lld\n", ans[find(1)]);

    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值