zoukankan      html  css  js  c++  java
  • 2015-2016 ACM-ICPC, NEERC, Northern Subregional Contest 训练报告

    题目链接:http://codeforces.com/gym/100801

    训练情况:AC8题,竟然读错了一道题,wa了挺多发。

    说明:AC的代码中加了文件读入。

    Problem A. Alex Origami Squares

    题意:给你一个h*w的矩形,让你分成三个正方形,输出正方形的最大边长。

    分析:直接在分成2*2份 3*1份 1*3份,取max就可以了

    AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e5+5;
    
    double h, w;
    
    int main () {
        freopen("alex.in", "r", stdin);
        freopen("alex.out", "w", stdout);
        cin >> h >> w;
        double ans = 0;
        ans = max(ans, min(h*1.0/3, w));
        ans = max(ans, min(h, w*1.0/3));
        ans = max(ans, min(h*1.0/2, w*1.0/2));
        printf("%.3lf
    ", ans);
        return 0;
    }
    View Code

    Problem B. Black and White

    题意:给你b和w,然后让你构造一个n*m的矩阵,是的‘@’符号的联通块个数时b,‘.’的联通块个数是w。

    分析:如果b和w一样,我们可以直接输出@和.间隔。否则我们假设b小于w,然后接下来的2*(b-1)行,我们交叉输出@@@和、、、,这样@还差一个联通块,.还差w-b+1个联通块。接下来我们输出2*(w-b+1)行,交叉输出@@@和@.@,就可以保证输出满足要求了。b>w交换一下就可以。

    AC代码:

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 int main(){
     6     ios_base::sync_with_stdio(false);
     7     cin.tie(0);
     8     freopen("black.in","r",stdin);
     9    freopen("black.out","w",stdout);
    10     int b,w,r,c;
    11     while(cin>>b>>w){
    12 
    13         if(b==w){
    14             cout<<1<<" "<<b+w<<endl;
    15             for(int i=1;i<=b+w;i++){
    16                 if(i%2==0){
    17                     cout<<"@";
    18                 }
    19                 else cout<<".";
    20             }
    21             cout<<endl;
    22         }
    23         else {
    24             char s1='@',s2='.';
    25             if(b>w){
    26                 swap(b,w);
    27                 swap(s1,s2);
    28             }
    29             int d=min(b,w);
    30             d--;
    31             cout<<d*2+max(b-d,w-d)*2<<" "<<3<<endl;
    32             for(int i=1;i<=d*2;i++){
    33                 if(i%2==1){
    34                     cout<<s1<<s1<<s1<<endl;
    35                 }
    36                 else cout<<s2<<s2<<s2<<endl;
    37             }
    38             d=max(b-d,w-d);
    39             for(int i=1;i<=d;i++){
    40                 for(int j=1;j<=2;j++){
    41                     if(j==1){
    42                         cout<<s1<<s1<<s1<<endl;
    43                     }
    44                     else cout<<s1<<s2<<s1<<endl;
    45                 }
    46             }
    47         }
    48 
    49     }
    50 
    51     return 0;
    52 }
    View Code

    Problem C. Concatenation

    题意:给你两个字符串s1和s2,然后在s1中选一个非空前缀,在s2中选一个非空后缀,问一共可以拼接多少不同的字符串。

    分析:直接计算s2中每个字符的个数(最后一个字符不进行统计),直接用s1和s2字符串长度想乘,计算全部情况,减去重复的即可。枚举s1的每一个字符(不包括第一个)在第二个中出现几次,求和就是重复出现的个数(可以直接相乘,不用加法).

    AC代码:

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 string s;
     6 long long mp[505];
     7 int main(){
     8     ios_base::sync_with_stdio(false);
     9     cin.tie(0);
    10     freopen("concatenation.in","r",stdin);
    11     freopen("concatenation.out","w",stdout);
    12     string s1,s2;
    13     while(cin>>s1>>s2){
    14         long long d1=s1.size();
    15         long long d2=s2.size();
    16         memset(mp,0,sizeof(mp));
    17         long long result=0;
    18         result=d1*d2;
    19         for(int i=0;i<d2-1;i++){
    20             mp[s2[i]]++;
    21         }
    22         for(int i=1;i<d1;i++){
    23             result-=mp[s1[i]];
    24         }
    25         cout<<result<<endl;
    26     }
    27 
    28     return 0;
    29 }
    View Code

    Problem D. Distribution in Metagonia

    题意:输入t,代表测试组数,接下来每次给你n,范围1e18,让你把n拆成不超过100个数字,这些数字的质因子只有2和3,。输出数字个数,然后

    分析:比赛的时候是暴力dfs过的,但是看了一下自己的dfs还有别人的AC思路,应该是刚好这个dfs顺序和贪心的顺序一样,只不过及时return了。然后贪心的话,每次找n可以整除的最大的2^w,然后再找最大p使得2^w*3^p<=n。这样可以保证w是递减的,p是递增的,然后每两个数字都不会互相整除。

    AC代码:

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 long long mod=1e18;
     6 long long pw2[105],pw3[105];
     7 int up[105];
     8 struct st{
     9     int x,y;
    10 }a[105];
    11 int number=0;
    12 int q=0;
    13 void dfs(long long sum){
    14    // cout<<sum<<endl;
    15     if(sum==0) {q=1;return;}
    16     if(q==1) return;
    17     for(int i=60;i>=0;i--){
    18         if(sum%pw2[i]!=0) continue;
    19         for(int j=up[i];j>=0;j--){
    20             if(sum>=pw2[i]*pw3[j]){
    21                 a[number].x=i;
    22                 a[number].y=j;
    23                 number++;
    24                 sum-=pw2[i]*pw3[j];
    25                 dfs(sum);
    26                 if(q==1)return;
    27                 sum+=pw2[i]*pw3[j];
    28                 number--;
    29             }
    30         }
    31     }
    32 }
    33 int main(){
    34     ios_base::sync_with_stdio(false);
    35     cin.tie(0);
    36     pw2[0]=1;
    37     pw3[0]=1;
    38     for(int i=1;i<=60;i++){
    39         pw2[i]=pw2[i-1]*2;
    40     }
    41     for(int i=1;i<=38;i++){
    42         pw3[i]=pw3[i-1]*3;
    43     }
    44     for(int i=0;i<=60;i++){
    45         long long now=1;
    46         for(int j=0;j<=40;j++){
    47             if(pw2[i]*pw3[j]>mod){
    48                 up[i]=j-1;
    49                 break;
    50             }
    51             now*=3;
    52         }
    53     }
    54     freopen("distribution.in","r",stdin);
    55     freopen("distribution.out","w",stdout);
    56     int t;
    57     long long n;
    58     cin>>t;
    59     while(t--){
    60         number=0;
    61         q=0;
    62         cin>>n;
    63         dfs(n);
    64         cout<<number<<endl;
    65         for(int i=0;i<number;i++){
    66             if(i!=0) cout<<" ";
    67             cout<<pw2[a[i].x]*pw3[a[i].y];
    68         }
    69         cout<<endl;
    70     }
    71     return 0;
    72 }
    View Code

    Problem E. Easy Arithmetic

    题意:就是给你一个运算式子,然后你可以添加+或者-,使得运算结果最大。

    分析:显然如果是加法,我们不需要添加,如果是减法,只需要在第一个数字之后添加+就可以了。添加加的前提是后一个是数字。

    AC代码:

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 int main(){
     6     ios_base::sync_with_stdio(false);
     7     cin.tie(0);
     8     freopen("easy.in","r",stdin);
     9     freopen("easy.out","w",stdout);
    10     string s;
    11     while(cin>>s){
    12         int d=s.size();
    13         int p=0;
    14         for(int i=0;i<d;i++){
    15             //cout<<i<<endl;
    16             if(s[i]=='-'){
    17                 p=1;
    18                 cout<<s[i];
    19                 i++;
    20                 if(i<d){
    21                     cout<<s[i];
    22                 }
    23             }
    24             else if(p==1){
    25                 if(s[i]=='0'){
    26                     cout<<"+"<<s[i];
    27                 }
    28                 else {
    29                     if(s[i]=='+'){
    30                         cout<<s[i];
    31                         p=0;
    32                         continue;
    33                     }
    34                     cout<<"+";
    35                     cout<<s[i];
    36                     p=0;
    37                 }
    38             }
    39             else {
    40                 cout<<s[i];
    41             }
    42         }
    43         cout<<endl;
    44     }
    45 
    46     return 0;
    47 }
    View Code

    Problem H. Hash Code Hacker

    题意:给你一个k,然后让你构造k个字符串,使得字符串按照题目给的哈希公式哈希值相同。

    分析:显然哈希公式是31进制,因此上一个字符-1,下一个字符+31就可以了。例如BB和Aa是等价的,可以构造一个长度为200的BBBBB字符串,然后选取两处替换成Aa就可以了。

    AC代码:

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 string s;
     6 int main(){
     7     ios_base::sync_with_stdio(false);
     8     cin.tie(0);
     9     freopen("hash.in","r",stdin);
    10     freopen("hash.out","w",stdout);
    11     int n;
    12     s="";
    13     for(int i=1;i<=200;i++){
    14         s+="B";
    15     }
    16     while(cin>>n){
    17         int ans=0;
    18         for(int i=0;i<100;i++){
    19                 if(ans==n) break;
    20             for(int j=i;j<100;j++){
    21                 ans++;
    22                 if(i==j){
    23                     s[i*2]='A';
    24                     s[i*2+1]='a';
    25                     cout<<s<<endl;
    26                     s[i*2]='B';
    27                     s[i*2+1]='B';
    28                 }
    29                 else {
    30                     s[i*2]='A';
    31                     s[i*2+1]='a';
    32                     s[j*2]='A';
    33                     s[j*2+1]='a';
    34                     cout<<s<<endl;
    35                     s[i*2]='B';
    36                     s[i*2+1]='B';
    37                     s[j*2]='B';
    38                     s[j*2+1]='B';
    39                 }
    40                 if(ans==n) break;
    41             }
    42         }
    43     }
    44 
    45     return 0;
    46 }
    View Code

    Problem J. Journey to the “The World’s Start”

    题意:给你n和t,n代表n个站台,t代表花费的时间,然后接下来一行给你n-1个数字,分别代表每次可以走小于等于i站的地铁票的价格,每种票买到以后可以无限使用,再下来一行给你n-2个数字,代表你在第2到第n-1站下车再上车花费的时间。现在问你从1出发,在花费时间小于等于t的情况下,最少花费多少可以到达n。(从1到n车上需要花费n-1时间)

    分析:首先对于题目,我们需要知道两点:1.如果x站的票可以在t时间内到达,那么x+1站的票也一定可以到达。2.一定是只买一种票花费最少。那么我们就可以二分x,判断x站的票是否可以达到我们可以dp+线段树维护,时间复杂度nlogn,然后对于每一个满足的x,维护一下价钱花费的后缀最小值,代表比x大的票都可以到达的最小花费。这样就可以完成这道题,总时间复杂度nloglog。(借用了一发赤耳的线段树模板)

    AC代码:

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
      4 #define mem(a,b) memset(a,b,sizeof(a))
      5 #define FIN freopen("in.txt","r",stdin)
      6 #define ls (id<<1)
      7 #define rs ((id<<1)|1)
      8 #define mid ((l+r)>>1)
      9 typedef unsigned long long ULL;
     10 typedef long long LL;
     11 
     12 const int maxn = 50000+5;
     13 
     14 int n, price[maxn];
     15 LL t, a[maxn],b[maxn];
     16 
     17 struct Node {
     18     LL minx;
     19 } node[maxn*4];
     20 void pushUp (int id, int l, int r) {
     21     node[id].minx = min(node[ls].minx, node[rs].minx);
     22     return ;
     23 }
     24 void build (int id, int l, int r) {
     25     if (l == r) {
     26         node[id].minx = a[l];
     27         return ;
     28     }
     29     build(ls, l, mid);
     30     build(rs, mid+1, r);
     31     pushUp(id, l, r);
     32 }
     33 void update (int id, int l, int r, int p, LL val) {
     34     if (l > r) return ;
     35     if (l == r && l == p) {
     36         node[id].minx = val;
     37         return ;
     38     }
     39     if (p <= mid) update(ls, l, mid, p, val);
     40     else if (p > mid)
     41         update(rs, mid+1, r, p, val);
     42     pushUp(id, l, r);
     43 }
     44 LL query (int id, int l, int r, int ql, int qr) {
     45     if (l == ql && r == qr) return node[id].minx;
     46     if (qr <= mid) return query(ls, l, mid, ql, qr);
     47     else if (ql > mid)
     48         return query(rs, mid+1, r, ql, qr);
     49     else {
     50         return min(query(ls, l, mid, ql, mid), query(rs, mid+1, r, mid+1, qr));
     51     }
     52 }
     53 bool judge(int x){
     54     for(int i=3;i<=n;i++){
     55         long long d=query(1,1,n,max(i-x,1),i-1)+query(1,1,n,i,i);
     56         update(1,1,n,i,d);
     57     }
     58     if(query(1,1,n,n,n)<=t) return true;
     59     return false;
     60 }
     61 void up(){
     62     for(int i=1;i<=n;i++){
     63         a[i]=b[i];
     64     }
     65     build(1,1,n);
     66 }
     67 int main () {
     68     ios_base::sync_with_stdio(false);
     69     cin.tie(0);
     70     freopen("journey.in","r",stdin);
     71     freopen("journey.out","w",stdout);
     72     cin>>n>>t;
     73     t -= (n-1);
     74     for (int i = 1; i <= n-1; ++i)
     75         cin >> price[i];
     76     for(int i=n-2;i>=1;i--){
     77         price[i]=min(price[i+1],price[i]);
     78     }
     79     b[1]=0;
     80     b[n]=0;
     81     for (int i = 2; i <= n-1; ++i)
     82         {cin >> a[i];
     83             b[i]=a[i];
     84         }
     85     a[1] = a[n] =0;
     86     build(1, 1, n);
     87     int result=100005;
     88     int low=1,high=n-1;
     89     while(low<=high){
     90         int md=(low+high)/2;
     91         if(judge(md)){
     92             high=md-1;
     93             result=min(result,price[md]);
     94         }
     95         else {
     96             low=md+1;
     97         }
     98         up();
     99     }
    100     cout<<result<<endl;
    101     return 0;
    102 }
    View Code

    Problem L. Lucky Chances

    题意:就是给你一个r*c的数组,然后对于每一个数字,如果他在上下左右四个方向,有几个方向是最大的,就可以得几分,问你这个数组一共可以得几分。

    分析:维护下行列前后缀最大值就可以,然后枚举就行了。(这个人代码真丑,竟然出现在我的博客上)

    AC代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
     4 #define mem(a,b) memset(a,b,sizeof(a))
     5 #define FIN freopen("in.txt","r",stdin)
     6 typedef unsigned long long ULL;
     7 typedef long long LL;
     8 
     9 const int maxn = 100+5;
    10 
    11 int n, m, a[maxn][maxn], h1[maxn][maxn], h2[maxn][maxn], l1[maxn][maxn], l2[maxn][maxn];
    12 
    13 int main () {
    14     freopen("lucky.in", "r", stdin);
    15     freopen("lucky.out", "w", stdout);
    16     //FIN;
    17     cin >> n >> m;
    18     for (int i = 1; i <= n; ++i) {
    19         for (int j = 1; j <= m; ++j)
    20             cin >> a[i][j];
    21     }
    22     for (int i = 1; i <= n; ++i) {
    23         for (int j = 1; j <= m; ++j) {
    24             h1[i][j] = max(h1[i][j-1], a[i][j]);
    25         }
    26     }
    27     for (int i = 1; i <= m; ++i) {
    28         for (int j = 1; j <= n; ++j) {
    29             l1[i][j] = max(l1[i][j-1], a[j][i]);
    30         }
    31     }
    32     for (int i = 1; i <= n; ++i) {
    33         for (int j = m; j >= 1; --j) {
    34             h2[i][j] = max(h2[i][j+1], a[i][j]);
    35         }
    36     }
    37     for (int i = 1; i <= m; ++i) {
    38         for (int j = n; j >= 1; --j) {
    39             l2[i][j] = max(l2[i][j+1], a[j][i]);
    40         }
    41     }
    42     int ans = 0;
    43     for (int i = 1; i <= n; ++i) {
    44         for (int j = 1; j <= m; ++j) {
    45             int x = a[i][j];
    46             if (x > h1[i][j-1])
    47                 ans++;
    48             if (x > h2[i][j+1])
    49                 ans++;
    50         }
    51     }
    52     for (int i = 1; i <= m; ++i) {
    53         for (int j = 1; j <= n; ++j) {
    54             int x = a[j][i];
    55             if (x > l1[i][j-1])
    56                 ans++;
    57             if (x > l2[i][j+1])
    58                 ans++;
    59         }
    60     }
    61     cout << ans << endl;
    62     return 0;
    63 }
    View Code
  • 相关阅读:
    HDU 5642 King's Order 动态规划
    HDU 5640 King's Cake GCD
    HDU 5641 King's Phone 模拟
    HDU 5299 Circles Game 博弈论 暴力
    HDU 5294 Tricks Device 网络流 最短路
    HDU 5289 Assignment rmq
    HDU 5288 OO’s Sequence 水题
    星际争霸 虚空之遗 人族5BB 操作流程
    Codeforces Beta Round #3 D. Least Cost Bracket Sequence 优先队列
    Codeforces Beta Round #3 C. Tic-tac-toe 模拟题
  • 原文地址:https://www.cnblogs.com/ls961006/p/9004350.html
Copyright © 2011-2022 走看看