zoukankan      html  css  js  c++  java
  • 2017-2018 ACM-ICPC, Asia Daejeon Regional Contest

    C

    有n个节点和m边条,求一条最长的路径,该路径(c1,c2,c3...cn)满足 不出现重复的节点,c和ci+1是邻居节点,且 c的邻居节点数量小于ci+1的邻居节点数量。

    记忆DFS遍历,每次递归计算的值都保存在数组里,这样复杂度相当于O(m)

     1 #include <bits/stdc++.h>
     2 #define INF 0x3f3f3f3f
     3 #define ll long long
     4 using namespace std;
     5 const int N = 1e5+10;
     6 vector<int> vs[N];
     7 int MAX, ans[N];
     8 int dfs(int v) {
     9     if(ans[v]!=0) return ans[v];
    10     int cnt = 0;
    11     for(auto u : vs[v]) {
    12         if(vs[u].size() > vs[v].size()) {
    13             cnt = max(cnt, dfs(u));
    14         }
    15     }
    16     ans[v] = cnt+1;
    17     return cnt+1;
    18 }
    19 int main() {
    20     int n, m, v, u;
    21     cin >> n >> m;
    22     for(int i = 1; i <= m; i ++) {
    23         cin >> v >> u;
    24         vs[v].push_back(u);
    25         vs[u].push_back(v);
    26     }
    27     for(int i = 0; i < n; i ++) {
    28         dfs(i);
    29         MAX = max(MAX, ans[i]);
    30     }
    31     cout << MAX << endl;
    32     return 0;
    33 }
    View Code

    D

    给定一个数字x,问一直使用x = f(x)这个函数是否可以将x变成1.

    f(x) 的定义是对每一位数进行平方求和。签到题

     1 #include <bits/stdc++.h>
     2 #define INF 0x3f3f3f3f
     3 #define ll long long
     4 using namespace std;
     5 map<int,int> mp;
     6 int f(int x) {
     7     int ans = 0;
     8     while(x) {
     9         int y = x%10;
    10         ans += y*y;
    11         x /= 10;
    12     }
    13     return ans;
    14 }
    15 int main() {
    16     int n;
    17     cin >> n;
    18     while(true) {
    19         n = f(n);
    20         if(n == 1) return 0*printf("HAPPY
    ");
    21         if(mp.count(n)) break;
    22         mp[n] = 1;
    23     }
    24     printf("UNHAPPY
    ");
    25     return 0;
    26 }
    View Code

    F

    已知边长和走的步数,求当前的位置。

    分而治之。对于当前边长为n的图,可以分为四份。

    如果在左下角,顺时针旋转了90°,相当于x和y值交换下。

    如果在右下角,逆时针旋转了90°,相当于x和y值交换下,对称看。

    如果在左上角,y值加n/2。

    如果在右上角,x值和y值都加n/2。

     1 #include <bits/stdc++.h>
     2 #define INF 0x3f3f3f3f
     3 #define ll long long
     4 using namespace std;
     5 const int N = 1e5+10;
     6 struct Point{
     7     int x, y;
     8 };
     9 Point dfs(int n, int m) {
    10     Point a;
    11     if(n == 2) {
    12         if(m == 0) a.x = 1, a.y = 1;
    13         else if(m == 1) a.x = 1, a.y = 2;
    14         else if(m == 2) a.x = 2, a.y = 2;
    15         else if(m == 3) a.x = 2, a.y = 1;
    16         return a;
    17     }
    18     int ans = n*n/4;
    19     int cnt = m%ans;
    20     a = dfs(n/2, cnt);
    21     if(m < ans) {
    22         swap(a.x, a.y);
    23     } else if(m < 2*ans) {
    24         a.y += n/2;    
    25     } else if(m < 3*ans) {
    26         a.x += n/2;
    27         a.y += n/2;
    28     } else {
    29         int x = n+1-a.y;
    30         int y = n/2+1 - a.x;
    31         return (Point){x, y};
    32     }
    33     return a;
    34 }
    35 
    36 int main() {
    37     int n, m;
    38     cin >> n >> m;
    39     Point p = dfs(n, m-1);
    40     printf("%d %d
    ",p.x,p.y);
    41     return 0;
    42 }
    View Code

    H

    有两个字符串,只有三个字符,R(石头)、S(剪刀)和P(布),求第二个在第一个在哪里开始比赛赢的数数最多,求数量。

    12 4

    RSPPSSSRRPPR

    RRRR

    第二个字符串从第4或第5位置开始可以赢3把,所以答案是3。

    题目可以转成成从哪里开始,位置一一对应是相同的数量。将第二个字符串反转,使用fft套模板就出答案了。

    主要是想到为什么对第二个字符进行反转,假设有两个字符串

    1 2 3 456

    RRRSSS

    SSPR

    1 2 3 4

    RPSS

    从第一个位置开始,一一对应是1+4,2+3,3+2,4+1,都是5 

    从第二个位置开始,一一对于是2+4,3+3,4+2,5+1,都是6

    这样就知道为什么反转了。只要对两个数组求卷积就行。

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <math.h>
     4 #define INF 0x3f3f3f3f
     5 #define ll long long
     6 using namespace std;
     7 const int N = 1e5+10;
     8 char s1[N], s2[N];
     9 const double PI = acos(-1.0);
    10 struct complex {
    11     double r,i;
    12     complex(double _r = 0,double _i = 0) {
    13         r = _r; i = _i;
    14     }
    15     complex operator +(const complex &b) {
    16         return complex(r+b.r,i+b.i);
    17     }
    18     complex operator -(const complex &b) {
    19         return complex(r-b.r,i-b.i);
    20     }
    21     complex operator *(const complex &b) {
    22         return complex(r*b.r-i*b.i,r*b.i+i*b.r);
    23     }
    24 };
    25 void change(complex y[],int len) {
    26     int i,j,k;
    27     for(i = 1, j = len/2;i < len-1;i++) {
    28         if(i < j)swap(y[i],y[j]);
    29         k = len/2;
    30         while( j >= k) {
    31             j -= k;
    32             k /= 2;
    33         }
    34         if(j < k)j += k;
    35     }
    36 }
    37 void fft(complex y[],int len,int on) {
    38     change(y,len);
    39     for(int h = 2;h <= len;h <<= 1) {
    40         complex wn(cos(-on*2*PI/h),sin(-on*2*PI/h));
    41         for(int j = 0;j < len;j += h) {
    42             complex w(1,0);
    43             for(int k = j;k < j+h/2;k++) {
    44                 complex u = y[k];
    45                 complex t = w*y[k+h/2];
    46                 y[k] = u+t;
    47                 y[k+h/2] = u-t;
    48                 w = w*wn;
    49             }
    50         }
    51     }
    52     if(on == -1)
    53         for(int i = 0;i < len;i++)
    54             y[i].r /= len;
    55 }
    56 
    57 const int MAXN = 400040;
    58 complex x1[MAXN], x2[MAXN];
    59 int a[MAXN/4], n, m;
    60 ll num[MAXN], ans[MAXN];
    61 void slove(char ch) {
    62     int len = 1;
    63     while(len < 2*n || len < 2*m)len <<= 1;
    64     for(int i = 0;i < n;i++)
    65         x1[i] = complex(s1[i]==ch,0);
    66     for(int i = n;i < len;i++)
    67         x1[i] = complex(0,0);
    68     for(int i = 0;i < m;i++)
    69         x2[i] = complex(s2[i]==ch,0);
    70     for(int i = m;i < len;i++)
    71         x2[i] = complex(0,0);
    72     fft(x1,len,1);
    73     fft(x2,len,1);
    74     for(int i = 0;i < len;i++)
    75         x1[i] = x1[i]*x2[i];
    76     fft(x1,len,-1);
    77     for(int i = 0;i < len;i++)
    78         num[i] = (long long)(x1[i].r+0.5);
    79        for(int i = 0; i < len; i ++) 
    80            ans[i] += num[i];
    81 }
    82 int main() {
    83     cin >> n >> m;
    84     cin >> s1 >> s2;
    85     for(int i = 0; i < n; i ++) {
    86         if(s1[i] == 'R') s1[i] = 'P';
    87         else if(s1[i] == 'P') s1[i] = 'S';
    88         else if(s1[i] == 'S') s1[i] = 'R';
    89     }
    90     for(int i = 0; i < m/2; i ++) swap(s2[i], s2[m-i-1]);
    91     slove('R');
    92     slove('S');
    93     slove('P');
    94     ll MAX = 0;
    95     for(int i = m-1; i < n+m-1; i ++) MAX = max(MAX, ans[i]);
    96     cout << MAX << endl;
    97     return 0;
    98 }
    View Code
  • 相关阅读:
    iOS9--适配系列教程(原文/译文)
    电梯调度设计思路及算法
    10大高频率单词筛选
    html知识点总结
    关于博客
    Java构造器内部的多态方法
    Java初学者必学的六大Java语言要点
    Java中的length字段和length()方法
    Java学习有方法有捷径
    Java 分隔符函数split的使用注意事项
  • 原文地址:https://www.cnblogs.com/xingkongyihao/p/9932439.html
Copyright © 2011-2022 走看看