• 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
  • 相关阅读:
    死工资的缓慢呆板已不能适合这个新型的商业社会。
    java获取前一天时间SimpleDateFormat,java判断某个时间段
    设置 DNS,防止 DNS 污染,清除 DNS 缓存ipconfig /flushdns
    win7 怎么设置开机直接进入桌面? netplwiz 命令
    AWS免费云服务套餐申请步骤及常见问题
    阿里云自定义镜像可以免费保存,ECS实例到期后自定义镜像手动快照不会被删除
    php获取字符串长度函数strlen和mb_strlen
    PHP HTML混写,PHP中把大块HTML文本直接赋值给字符串变量的方法
    人工智能跟脑神经科学没有关系。没有出差错的机会,就没有进化的可能。要想自己把事情做成功,就需要弄清楚事物的本质。
    python GIL 全局锁,多核cpu下的多线程性能究竟如何?
  • 原文地址:https://www.cnblogs.com/ls961006/p/9004350.html
Copyright © 2020-2023  润新知