• HDU2017多校联合 contest 1


    1001.  Add More Zero

    给出m,求解最小的k满足10^k <= 2^m。两边同时取以10为底的对数答案就出来了。

    #include "bits/stdc++.h"
    using namespace std;
    int main(int argc, char const *argv[])
    {
        int n; int kcase = 0;
        while (scanf("%d", &n) != EOF) {
            int ans = (int)n*log10(2.0);
            printf("Case #%d: %d
    ", ++kcase, ans);
        }
        return 0;
    }
    View Code

    1002. Balala Power!

    题意:

    给出n个字符串。每个字符代表一个0-25的值,各个字符的值要求不相同,而且对于长度大于1的字符串,第一个字符不能赋值为零。

    思路:

    直接模拟,从低位向高位进位,最后考虑下第一个字符时赋值是零的情况。

    #include "bits/stdc++.h"
    using namespace std;
    typedef long long LL;
    const int maxn = 100100;
    const int mod = 1e9 + 7;
    char s[maxn];
    int da[maxn][30];
    int ra[maxn];
    int maxx;
    bool head[maxn];
    LL pow_mod(int n,int m){
        LL ans=1,base=n;
        while(m){
            if(m&1) ans = (ans*base)%mod;
            base = (base*base)%mod; m>>=1;
        }
        return ans;
    }
    int cmp(int x, int y) {
        for (int i = maxx; i >= 0; i--) {
            if (da[i][y] > da[i][x]) return -1;
            else if (da[i][y] < da[i][x]) return 1;
        }
        return 0;
    }
    LL value() {
        LL ans = 0;
        for (int i = 0; i < 26; i++) {
            for (int j = 0; j < maxx; j++) {
                ans = (ans + ra[i]*da[j][i]%mod*pow_mod(26, j)%mod)%mod;
            }
        }
        return ans;
    }
    void change(int x, int f) {
        for (int i = 0; i < 26; i++) {
            if (ra[i] == x) {
                swap(ra[i], ra[f]);
                if (head[i]) return change(x+1, i);
                return;
            }
        }
    }
    int main(int argc, char const *argv[])
    {
        int n; int kcase = 0;
        while (scanf("%d", &n) != EOF) {
            memset(da, 0, sizeof(da));
            memset(head, false, sizeof(head));
            memset(ra, 0, sizeof(ra));
            maxx = 0;
            for (int i = 0; i < n; i++) {
                scanf("%s", s); int len =strlen(s);
                maxx = max(maxx, len);
                for (int j = len-1; j >= 0; j--) {
                    int t = s[j] - 'a';
                    if (j == 0 && len != 1) head[t] = true;
                    da[len-1-j][t]++;
                }
            }
            for (int i = 0; i < 26; i++) {
                for (int j = 0; j < maxx; j++) {
                    if (da[j][i] > 25 && j + 1 >= maxx) maxx++;
                    int t = da[j][i];
                    da[j + 1][i] += t/26, da[j][i]=t%26;
                }
            }
            for (int i = 0; i < 26; i++) {
                int k = 0;
                for (int j = 0; j < 26; j++) {
                    int t = cmp(i, j);
                    if (t == 0 && i < j) k++;
                    else if (t == 1) k++;
                }
                ra[i] = k;
            }
            int z = 0;
            for (; z < 26; z++) if (ra[z] == 0) break;
            if (head[z]) change(1,z);
            printf("Case #%d: %lld
    ", ++kcase, value());
        }
        return 0;
    }
    View Code

     

    1003. Colorful Tree

    题意:

    有一棵树,每个节点都有一个颜色,定义任意两点之间的长度为两点之间的出现的不同颜色的数量。求出整棵树上的所有长度和。

    思路:

    我参考的是http://blog.csdn.net/Bahuia/article/details/76141574里的文章,博主写的很好,还有图可以参考。

    按照我自己的理解,对于每棵树先假设每条路上都有所有的颜色,那么路的总长度就应该是n*(n-1)/2*tot。然后考虑反面,对于颜色color[i]来说在一个联通区域没有出现color[i],那么减掉多加的部分。将这个树按照颜色的联通区域进行分块,然后进行统计。

    利用树形dp的思想,从树根开始dfs。当访问并且回溯到节点u的时候,根据节点u的颜色,判断子树上不含有颜色u并且和u联通的联通区域的大小(由u和他同颜色的子节点所包围的不含颜色u的最大联通区域)。从叶子节点向根推进,使得最后的联通区域集中在根节点。最后在对整棵树做统计。

    #include "bits/stdc++.h"
    using namespace std;
    typedef long long LL;
    const int maxn = 200010;
    LL ans = 0;
    bool vis[maxn];
    std::vector<int> tree[maxn];
    LL sum[maxn], sz[maxn], color[maxn];
    int dfs(int u, int fa) {
        sz[u] = 1;
        LL allson = 0; // 表示u的子树上不含颜色u的联通块的个数
        for (int i = 0; i < tree[u].size(); i++) {
            int v = tree[u][i];
            if (v == fa) continue;
            int lastsum = sum[color[u]]; // 记录递归以前color[u]的个数
            sz[u] += dfs(v, u);
            LL add = sum[color[u]] - lastsum; //add记录的是以color[u]为根节点的最高子树的大小
            ans += (sz[v] - add)*(sz[v] - add - 1)/2;//不含color[u]的联通块的大小是sz[u]-add
            allson += sz[v] -add; //记录联通块的大小。
        }
        sum[color[u]] += allson + 1;//不含color[u]树的大小要增加。
        return sz[u];
    }
    int main(int argc, char const *argv[])
    {
        int kcase = 0, n;
        while (scanf("%d", &n) != EOF) {
            ans = 0; int tot = 0;
            memset(sum, 0, sizeof(sum));
            memset(vis, false, sizeof(vis));
            for (int i = 1; i <= n; i++) {
                scanf("%lld", &color[i]);
                if (!vis[color[i]]) tot++;
                vis[color[i]] = true;
                tree[i].clear();
            }
            for (int i = 1; i < n; i++) {
                int a, b; scanf("%d%d", &a, &b);
                tree[a].push_back(b);
                tree[b].push_back(a);
            }
            printf("Case #%d: ", ++kcase);
            LL res = (LL)n*(LL)(n - 1)/2*(LL)tot; 
            if (tot == 1) { 
                printf("%lld
    ", res);
                continue;
            }
            dfs(1, -1);
            for (int i = 1; i <= n; i++) {     
                if (!vis[i]) continue;
                ans += (n-sum[i])*(n-sum[i]-1LL)/2LL;
            }
            printf("%lld
    ", res - ans);
        }
        return 0;
    }
    View Code

     1006.Function

    题意:

    对于集合a 有n个元素(0~n-1),对于集合b有m个元素(0~m-1),求出映射f的个数使得f(i)=bf(ai) 。

    思路:

    先观察映射f : f(i) = bf(ai),设xn表示xxn次下标(x-x映射),将ai进行n次映射之后变成了f(i) = bnf(ani)。若a的循环节为n,则此时bn应该等于b所以得到结论,要使得映射存在,必须a的循环节是b的整数倍。

    将a和b分别表示为几个不相交的轮转的乘积,根据乘法计数原理进行统计。

    #include "bits/stdc++.h"
    using namespace std;
    typedef long long LL;
    const int maxn = 1e6 + 10;
    const int MOD = 1e9 + 7;
    int a[maxn], b[maxn];
    bool vis[maxn];
    std::vector<int> la;
    std::vector<int> lb;
    void get(int s[], vector<int> &res, int l) {
        memset(vis, false, sizeof(vis));
        for (int i = 0; i < l; i++) {
            if (vis[i]) continue;
            int t = s[i]; int len = 0;
            while (!vis[t]) {
                len++;
                vis[t] = true;
                t = s[t];
            }
            res.push_back(len);
        }
    } 
    int main(int argc, char const *argv[]) 
    {
        int n, m;
        int kcase = 0;
        ios::sync_with_stdio(false);
        while (cin >> n >> m) {
            la.clear(); lb.clear();
            for (int i = 0; i < n; i++) cin >> a[i];
            for (int j = 0; j < m; j++) cin >> b[j];
            get(a, la, n); get(b, lb, m);
            int lena = la.size();
            int lenb = lb.size();
            LL ans = 1;
            for (int i = 0; i < lena; i++) {
                LL  res = 0;
                for (int j = 0; j < lenb; j++) {
                    if (la[i]%lb[j] == 0) res = (res + lb[j])%MOD;  
                }
                ans = res*ans%MOD;
            }
            printf("Case #%d: %lld
    ", ++kcase, ans);
        }
        return 0;
    }
    View Code

    1011. KazaQ's Socks

    题意:

    一个人有n(LL)双袜子, 每次从柜子里取出编号最小的袜子穿上,晚上将袜子放到框里。当某天晚上有n-1双袜子要洗,那么当晚洗干净,第二天晚上将这n-1双袜子放到柜子里,问第q天他穿的是哪个编号的袜子。

    多写几组样例就会发现规律,如有五双袜子:12345(12341235)。

    #include "cstdio"
    #include "cmath"
    #include "cstring"
    #include "algorithm"
    using namespace std;
    typedef long long LL;
    int main(int argc, char const *argv[])
    {
        LL n, q;
        int kcase = 0;
        while (scanf("%lld%lld", &n, &q) != EOF) {
            printf("Case #%d: ", ++kcase);
            if (n >= q) printf("%lld
    ", q);
            else {
                q -= n; q %= 2*(n - 1);
                if (q == 0) printf("%lld
    ", n);
                else if (q < n) printf("%lld
    ", q);
                else printf("%lld
    ", q - n + 1);
            }
        }
        return 0;
    }
    View Code

    这次的题就补到这里吧,感觉智商已经欠费╮(╯﹏╰)╭╮(╯﹏╰)╭



    ​​

  • 相关阅读:
    Python对JSON的操作 day3
    Python 文件操作 day2
    Python 字符串常用方法 day2
    Python字典 day2
    Python基础学习(day1)
    Excel图表转成图片
    hadoop —— MapReduce:统计访问所有独立IP个数 、 统计网站子目录访问次数 、 统计每个IP访问的子目录数
    Java -D命令对应的代码中获取-D后面的参数 和 多个参数时-D命令的使用
    hadoop —— teragen & terasort
    C# 计时器 以“天时分秒毫秒”形式动态增加显示
  • 原文地址:https://www.cnblogs.com/cniwoq/p/7241376.html
Copyright © 2020-2023  润新知