zoukankan      html  css  js  c++  java
  • CUG2012年暑期ACM训练赛(单人赛)

    A题是一个模拟或者说是搜索吧

    就跟倒可乐的问题差不多

    原题是ZOJ1005题

    View Code
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
     
    char ans[101000][10];
    int main(){
        int tcase;
        scanf("%d", &tcase);
        //int flag = 0;
        while(tcase --){
            int count = 0;
            int x, y, z;
            scanf("%d%d%d", &x, &y, &z);
            char a, b;
            if(x < y){
                a = '1';
                b = '2';
            }else{
                a = '2';
                b = '1';
                swap(x, y);
            }
            //int xx = 0, yy = 0;
            sprintf(ans[count++], "F(%c)\n", b);
            sprintf(ans[count++], "P(%c,%c)\n", b, a);
            int now = y - x;
            while(now != z){
               // printf("%d %d %d %d\n", count, x , y,z );
     
                if(now > x){
                    sprintf(ans[count++], "E(%c)\n", a);
                    sprintf(ans[count++], "P(%c,%c)\n", b, a);
                    now -= x;
                }else{
                    sprintf(ans[count++], "E(%c)\n", a);
                    sprintf(ans[count++], "P(%c,%c)\n", b, a);
                    sprintf(ans[count++], "F(%c)\n", b);
                    sprintf(ans[count++], "P(%c,%c)\n", b, a);
                    now = (now + y - x) % y;
                }
                if(count > 2500)break;
            }
            if(count > 2500){
                puts("Impossible!");
     
            }else{
            printf("%d\n", count);
            for(int i = 0; i < count ; i ++)
            printf("%s", ans[i]);}
            if(tcase != 0)
            puts("");
        }
        return 0;
    }

    B题是一个凸包问题,我完全不会= =、

    学弟们都会做。。。。我弱爆了啊

    这题用的是ZY给我的模板,然后直接套的,最后加上一个圆的周长就行了

    View Code
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
     
    using namespace std;
     
    struct point{
        double x, y;
    }p[1010], stack[1010];
    int n, top;
    double mul(point a, point b, point c){
        return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
    }
    double dis(point a, point b){
        return sqrt((a.x -b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
    }
    int cmp(const void *a, const void *b){
        point c = *(point *)a;
        point d = *(point *)b;
        double k = mul(p[0], c, d);
        if(k < 0 || (!k && dis(c, p[0]) > dis(d, p[0])) )
          return 1;
        return -1;
    }
    void convex(){
        for(int i = 1; i < n; i ++){
            point tmp;
            if(p[i].y < p[0].y || (p[i].y == p[0].y && p[i].x < p[0].x)){
                swap(p[i], p[0]);
            }
        }
        qsort(p + 1, n - 1, sizeof(p[0]), cmp);
        stack[0] = p[0];
        stack[1] = p[1];
        top = 1;
        for(int i = 2; i < n; i ++){
            while(top >= 1 && mul(stack[top - 1], stack[top], p[i]) <= 0)
              top --;
            top ++;
            stack[top] = p[i];
        }
    }
     
     
    int main(){
        double r;
        while(~scanf("%d%lf", &n, &r)){
            for(int i = 0; i < n; i ++){
                scanf("%lf%lf", &p[i].x, &p[i].y);
            }
            convex();
            double ans = 0;
            for(int i = 0; i < top ;i ++){
                ans += dis(stack[i], stack[i+1]);
            }
            ans += dis(stack[top], stack[0]);
            ans += 2 * acos(-1.0) * r;
            printf("%.0f\n", ans);
        }
        return 0;
    }

    C题就不说了,暴力能过,数据弱啊。。。。

    View Code
    #include<cstdio>
     
    int a[10000 + 10];
    int main(){
        int tcase;
        scanf("%d", &tcase);
        while(tcase --){
            int n;
            scanf("%d", &n);
            for(int i = 1; i <= n; i ++)
              scanf("%d", a + i);
            int flag = 0;
            for(int i = 2; i <= n - 1; i ++){
                for(int j = 1; j < i; j ++){
                    for(int k = i + 1; k <= n; k ++){
                        if(a[j] + a[k] == 2 * a[i]){
                            flag = 1;
                            break;
                        }
                    }
                    if(flag)
                      break;
                }
                if(flag)
                  break;
            }
            if(flag)
              puts("Yes");
            else
              puts("No");
        }
        return 0;
    }

    D题也不说了,不会做,搞不懂题,这么多人WA了,没有人过、。

    E题纯数据结构+模拟啊,不想敲了,写起来太麻烦了

    F题我开始用n^2的DP 直接 TLE了,后来ZY说用NlogN,然后就直接过了。。

    View Code
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
     
    using namespace std;
     
    struct node{
        int x, y;
        friend bool operator < (const node &a, const node &b){
            return a.x < b.x;
        }
    }p[10010];
    int dp[10010];
    int a[10010];
    int binary_search(int c[],int len,int v)
    {
        int left=0,right=len-1,mid=left+(right-left)/2;
        while(left<=right){
            if(v>c[mid])   left=mid+1;
            else if(v<c[mid])   right=mid-1;
            else return mid;
            mid=left+(right-left)/2;
        }
        return left;
    }
    int main(){
        int tcase;
        scanf("%d", &tcase);
        while(tcase --){
            int n;
            scanf("%d", &n);
            for(int i = 0; i < n; i ++){
                scanf("%d%d", &p[i].x, &p[i].y);
                dp[i] = 1;
            }
            sort(p, p + n);
            /*
            for(int i = 1; i < n; i ++){
                for(int j = 0; j < i; j ++){
                    if(p[i].y> p[j].y)
                      if(dp[i] < dp[j] + 1)
                        dp[i] = dp[j] + 1;
                }
            }
            */
            int top = 0;
            a[top++] = p[0].y;
            for(int i = 1; i < n; i ++){
                if(a[top - 1] < p[i].y)
                  a[top++] = p[i].y;else{
                      int tmp = binary_search(a, top, p[i].y);
                      a[tmp] = p[i].y;
                  }
            }
     
            int ans = 0;
            /*
            for(int i = 0; i < n; i ++)
              if(ans < dp[i])
                ans = dp[i];
                */
            printf("%d\n", top);
        }
        return 0;
    }

    G题不知道110是怎么出来的

    H题还是有那么点意思的

    我的思路是,对每一个点进行DFS

    DFS的过程中,每走到一个C就把该点变成*

    这样就能计数了

    View Code
    #include<cstdio>
    #include<cstring>
     
    int vis[10000 + 10];
    char map[110][110];
    int n,m;
    int dir[8][2]={
        1,1,1,0,1,-1,-1,1,-1,0,-1,-1,0,1,0,-1
    };
    void dfs(int x, int y){
        map[x][y] = '*';
        for(int i = 0; i < 8; i ++){
            int xx = x + dir[i][0];
            int yy = y + dir[i][1];
            if(map[xx][yy] == 'C'){
                dfs(xx, yy);
            }
        }
    }
    int main(){
        scanf("%d%d", &n, &m);
        for(int i = 0; i < n; i ++)
          scanf("%s", map[i]);
        memset(vis, -1, sizeof(vis));
        int count = 0;
        for(int i = 0; i < n; i ++){
            for(int j = 0; j < m ; j ++)
              if(map[i][j] == 'C'){
                  dfs(i, j);
                  count ++;
              }
        }
        printf("%d\n", count);
        return 0;
    }

    I题用java做的

    当时没有编译器

    直接vim编写的,那当然错误一大堆

    后来还是装了eclipse了

    View Code
    import java.math.BigInteger;
    import java.util.Scanner;
      
    public class Main{
        public static void main(String args[]){
            Scanner cin = new Scanner(System.in);
            int t;
            t = cin.nextInt();
            while(t-- != 0){
                int n;
                n = cin.nextInt();
                n --;
                BigInteger a = cin.nextBigInteger();
                while(n-- != 0){
                    BigInteger b = cin.nextBigInteger();
                    //System.out.println(b);
                    //a.subtract(b);
                    //System.out.println(a.subtract(b));
                    a = a.subtract(b);
                }
                System.out.println(a);
            }
        }
    }

    J题不会做

    做了6题,感觉最遗憾的当是图论那题和最后一题了,不会啊。。继续加油学吧

    --------------------------------更新----------------------------------------------

    本来不想做的,数论不会啊。。。。但怕第一的位子没了。。还是做了

    不过做是做了,也是看着解题报告做的= =原题

    http://poj.org/problem?id=2154 就是这题了,一看出处吓死了,楼教主的原题啊。。

    一开始的时候以为是polya定理来做,然后就直接套模板敲了

    不过后来发现不一样啊,并不翻转

    然后就找特殊情况加着求了,然后果断TLE

    10亿的数据啊。。。

    后来问了dream神,他给我讲了一通

    然后他告诉我是哪题了,再去看解题报告 。。。

    很遗憾。。。没有完全看懂。。。大概的理解了。。

    解法也在下面了。。

    View Code
    #include<iostream>
    #include<math.h>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    /*
    置换只有旋转一种方式,那么共有n个置换
    基本知识:环的个数为gcd(n , i) , 长度L=n / gcd(n , i)   其中 i 为转的位子数
    普通求法: ∑n^( gcd(n,i) )  0<=i<n  复杂度过高
    优化:枚举环的长度L
    枚举优化: L可以从1取到sqrt(n) ,因为L|n , n/L | n
    对于每个L,我们再看有几个i满足条件
    n/L = gcd(n , i)
    那么令 a=n/L = gcd(n , i) , 再设i = at
    那么当且仅当gcd(L,t)=1时候,才有gcd(n,i) = a
    显然满足条件的i的个数就是t的个数也就是phi(L)
    那么最后统计一下就是 ∑(phi(L) * N^(L-1) ) % p  (L即枚举值)
    */
    
    const int maxn = 50000;
    bool IsNotPrime[maxn]; // 判断是否为素数.
    int PrimeList[maxn]; // 素数列表.
    int PrimeNum;
    
    void Prime_Linear(void)
    { // 速度比朴素筛法快2倍以上,该筛法进行稍微修改即可用于求欧拉函数Phi[].
        int i, j;
        memset(IsNotPrime, 0, sizeof(IsNotPrime)); // 初始赋值所有数都是素数.
        IsNotPrime[1] = 1; IsNotPrime[0] = 1; // 0和1不是素数.
        PrimeList[0]=2;
        for (i = 4; i < maxn; i += 2) IsNotPrime[i] = 1; // 除2以外的所有偶数都不是素数.
        PrimeNum = 1;
        for (i = 3; i < maxn; i += 2)
        {
            if (!IsNotPrime[i])
            { // 如果是素数则加入素数列表.
                PrimeList[PrimeNum++] = i;
            }
            // 注意:这里与朴素筛法不同,即使合数也要进行筛.
            // 因为这里素数只筛它的素数倍,那么有些合数就可能没被筛掉.
            // 而这些合数就需要合数来晒,而且只要筛到它的最小质因子倍即可(想想为什么?).
            for (j = 0; j < PrimeNum && i * PrimeList[j] < maxn; j++)
            {
                IsNotPrime[i * PrimeList[j]] = 1;
                if (i % PrimeList[j] == 0)
                { // 说明PrimeList[j]是i的最小质因子,即i * PrimeList[j]的最小质因子,则跳出.
                    break;
                }
            }
        }
    }
    
    int modular_exponent(int a, int b, int n){
        int ret = 1;
        a %= n;
        for( ; b; b >>= 1, a = (int)( (long long )a) * a % n ){
            if(b & 1)
              ret = (int)((long long )ret) * a % n;
        }
        return ret;
    }
    int euler(int x){
        int res = x;
        for(int i = 0; i < PrimeNum && PrimeList[i] * PrimeList[i] <= x; i ++){
            if(x % PrimeList[i] == 0){
                res = res / PrimeList[i] * (PrimeList[i] -1);
                while(x % PrimeList[i] == 0){
                    x /= PrimeList[i];
                }
            }
        }
        if(x > 1)
            res = res / x * ( x - 1);
        return res;
    }
    int main(){
        int tcase;
        scanf("%d", &tcase);
        Prime_Linear();
        while(tcase --){
            int n, p;
            scanf("%d%d", &n, &p);
            int ans = 0;
            int i;
            for( i = 1; i * i < n; i ++)
            if(n%i == 0){
                ans = (ans + euler(i) % p * modular_exponent(n, n/i-1, p)
                       + euler(n/i) %p * modular_exponent(n, i-1, p)) % p;
            }
            if (i * i == n)
            ans = (ans + euler(i) * modular_exponent(n, i-1, p)) % p;
            printf("%d\n", ans);
        }
        return 0;
    }

    D题继续不懂,他说我没有看清题 ?听说是CF的原题。。。

    E题继续打死不写

    G题是网络流啊,110也知道是怎么出来的了

    因为题目中已经说清楚了是无向边

    不过数据中竟然给了2 3 和3 2 这种情况。。。。。这。。。。太坑了啊。。

    因为边可能重边之类的

    所以要用floyd来计算最短路了,即所有点之间的最短值了。。。

    然后就是用网络流了。。。

    不会啊,还不理解。。。

    还是巩固下吧

     -----------------------继续更新--------------------------

    C题,原来没看清题啊。。跪 

    出现的数一定是从1-n并且全部填完的。。。这样的话,就跟逆序数那题差不多啊。。

    View Code
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    
    int a[10000+10];
    int flag[10000+10];
    int main(){
        int tcase;
        scanf("%d", &tcase);
        while(tcase --){
            int n;
            memset(flag, 0, sizeof flag);
            scanf("%d", &n);
            for(int i = 0; i < n; i ++) scanf("%d", a + i);
            int f = 0;
            /*
            for(int i = 0; i < n; i ++){
                flag[ a[i] ] = 1;
                for(int j = a[i] + 1; j < n -a[i]; j ++){
                    if(flag[ a[i] - j] + flag[ a[i] + j] == 1){
                        f = 1;
                        break;
                    }
                }
                if(f)
                  break;
            }
            */
            //JZ同学说只要大于5一定是YES了Orz
            if(n >= 5){
                puts("Yes");
                continue;
            }
            for(int i = 0; i < n; i ++){
                for(int j = 0; j < i; j ++){
                    for(int k = i + 1; k < n; k ++){
                        if(a[i] * 2 == a[j] + a[k]){
                            f = 1;
                            break;
                        }
                    }
                }
            }
            if(f)
              puts("Yes");
            else
              puts("No");
        }
        return 0;
    }

    D题,单调队列

    见这个

    http://www.cnblogs.com/louzhang/archive/2012/08/01/2617837.html

     这个就更新到这吧,博客也写的挫。。。写的也累死了

  • 相关阅读:
    服务器搭建域控与SQL Server的AlwaysOn环境过程(二) 搭建客户端节点 服务器
    服务器搭建域控与SQL Server的AlwaysOn环境过程(一) 搭建域控服务器
    React中的AES加解密请求
    React项目构建(利用webpack打包)
    解决IIS服务器部署 字体图标找不到的原因
    iOS开发之视频播放31次、15次后错误,NSLocalizedFailureReason=此媒体所需的解码器正忙
    iOS开发之视频播放功能、边播放边缓存
    iOS开发之获取最上层 Window
    iOS开发之APP启动视频
    iOS开发之图片base64编码处理
  • 原文地址:https://www.cnblogs.com/louzhang/p/2613689.html
Copyright © 2011-2022 走看看