2016湖南湘潭邀请赛题解:2016年“长城信息”杯中国大学生程序设计比赛中南地区邀请赛(迟来的题解)

提交OJ:http://202.197.224.59/OnlineJudge2/index.php/Problem/index/p/13/

题号:xtu 1243-1252

xtu 1243  A题  2016

Given a 2 matrix

,

find 7.

 

Special Note: The problem is intended to be easy. Feel free to think why the problem is called 2016 if you either:

  1. find it hard to solve;
  2. or, solved all the other problems easily.

Input

The input contains at most 40 sets. For each set:

The first line contains an integer n (100000).

The second line contains 2 integers 12.

The third line contains 2 integers 22.

(7)

Output

For each set, a 7.

Sample Input

2
1 1
1 2
2016
1 1
1 2

Sample Output

2 3
3 5
1 0
0 1
思路:大数取模+矩阵乘法;
AC代码:
#include <stdio.h>
#include <string.h>
const int M=500000;
int a[M][2][2];
char s[M];
int main()
{
    int n;
    while(scanf("%s",s)!=EOF)
    {
      int mod=0,n=0,x1,y1,x2,y2,len=strlen(s);
      scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
      a[1][0][0]=a[0][0][0]=x1;
      a[1][0][1]=a[0][0][1]=y1;
      a[1][1][0]=a[0][1][0]=x2;
      a[1][1][1]=a[0][1][1]=y2;
      for(int i=2;i<=M;i++)
      {
          mod++;
          a[i][0][0]=(a[i-1][0][0]*x1+a[i-1][0][1]*x2)%7;
          a[i][0][1]=(a[i-1][0][0]*y1+a[i-1][0][1]*y2)%7;
          a[i][1][0]=(a[i-1][1][0]*x1+a[i-1][1][1]*x2)%7;
          a[i][1][1]=(a[i-1][1][0]*y1+a[i-1][1][1]*y2)%7;
          if(a[i][0][0]==x1&&a[i][0][1]==y1&&a[i][1][0]==x2&&a[i][1][1]==y2)
            break;
      }
      a[0][0][0]=a[mod][0][0];
      a[0][0][1]=a[mod][0][1];
      a[0][1][0]=a[mod][1][0];
      a[0][1][1]=a[mod][1][1];
      for(int i=0;i<len;i++)
        n=(n*10+s[i]-'0')%mod;
      printf("%d %d\n%d %d\n",a[n%mod][0][0],a[n%mod][0][1],a[n%mod][1][0],a[n%mod][1][1]);
    }
    return 0;
}

 

xtu 1244  B题  Gambling

Gambling

In ICPCCamp, gambling is conducted as follow. A player will draw balls from an opaque bag containing b green balls, or Third Prize otherwise.

Bobo is going to take part in the above gambling. Therefore, it is very important for him to work out the probability of winning each prize.

Input

The input contains at most 40 sets. For each set:

Three integers 3).

Output

For each set, three irreducible fractions C denote the probability of winning First Price, Second Price, and Third Price, respectively.

Sample Input

1 1 1
1 2 3

Sample Output

1/3 1/3 1/3
7/12 4/15 3/20

题意:
有a个红球,b个绿球,c个黄球,先拿完a个红球一等奖,先拿完b个绿球二等奖,c个黄球三等奖。求各个奖获奖的概率。

 

思路:

分析首先拿完红球,即拿一等奖的概率:

我们假设拿完红球后继续拿,也就是拿完所有的球。

接下来逆向思考,红球不可能是最后一个,最后一个只可能是黄球或绿球,我们可以把摸出来的球的顺序逆置,比如(红,黄,红,绿,绿,黄,绿)逆置之后就是(绿,黄,绿,绿,红,黄,红),你会发现,你第一个摸到的球的颜色一定会是黄、绿当中的一种,而摸到的第二种颜色的球一定是黄绿当中未摸到过的,这样的话就很好计算了。

那么如果最后一个球是黄球,它的概率就是c/(a+b+c),除去黄球,最后一个是绿球的概率就是b/(a+b)。此时概率就是两者相乘。

最后一个球是绿球的话也是这样分析。

二等奖和三等奖也如上分析即可。


AC代码 :
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long LL;
LL a,b,c;
LL gcd(LL a,LL b)
{
    return b==0?a:gcd(b,a%b);
}
void cacl(LL a, LL b, LL c,int flag)
{
    LL z=b*c*(2*a+b+c);
    LL m=(a+b+c)*(a+b)*(a+c);
    LL g=gcd(m,z);
    printf("%I64d/%I64d",z/g,m/g);
    if(flag<=2)  printf(" ");
    else printf("\n");
}

int main()
{
    while(~scanf("%lld%lld%lld",&a,&b,&c))
    {
        cacl(a,b,c,1);
        cacl(b,a,c,2);
        cacl(c,a,b,3);
    }
    return 0;
}

 

 

xtu 1245  C题  Hamiltonian Path

Hamiltonian Path

In ICPCCamp, there are n cities and m directed roads between cities. The i-th road going from the v.

Bobo wants to make big news by solving the famous Hamiltonian Path problem. That is, he would like to visit all the n cities one by one so that the total distance travelled is minimized.

Formally, Bobo likes to find distinct integers y-th city.

Input

The input contains at most 30 sets. For each set:

The first line contains 2 integers 5).

The i-th of the following m lines contains 3 integers 4).

Output

For each set, an integer denotes the minimum total distance. If there exists no plan, output -1 instead.

Sample Input

3 3
1 2 1
1 3 1
2 3 1
3 2
1 2 1
1 3 2

Sample Output

2
-1

思路:只能1-2-3-4-。。。-n;1ai<bin。。。

AC代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int M=100000+10;
int a[M];
int main()
{
    int n,m;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
     memset(a,0,sizeof(a));
     int sum=0,k=0;
     for(int i=1;i<=m;i++)
     {
         int x,y,c;
         scanf("%d %d %d",&x,&y,&c);
         if(y==x+1)
         {
            if(a[x]==0)
            {
                a[x]=c;
                k++;
            }
            else
                a[x]=min(a[x],c);
         }
     }
     if(k<n-1) {printf("-1\n");continue;}
     for(int i=1;i<n;i++) sum+=a[i];
     printf("%d\n",sum);
    }
    return 0;
}

  

xtu 1246  D题  Heartstone
Heartstone

Bobo is playing Heartstone. There are n minions in the battlefield. The i-th minion has i hit points (HP).

Bobo uses two kinds of magic. The one is Arcane Shot and the other is FrostboltArcane Shot can deal two points damage to a minion (that is to decrease the minion's HP by two), while Frostbolt can deal three points damage. A minion is killed when its HP is less or equal to zero.

Let ).

Input

The input contains at most 30 sets. For each set:

The first line contains 2 integers 5).

The second line contains n integers 4).

Output

For each set, an integer denotes ).

Sample Input

3 2
1 2 3
3 2
2 2 2

Sample Output

6
6

题意+思路(借鉴他人):

炉石游戏,有A 和F魔法,问给你n个带血量的小兵,你在每次最多拥有f(0)…f(m)个A魔法,f(0)代表最多有0个A魔法,的情况下,最少需要几个F魔法才能击杀所有的小兵

要控制魔法F的使用就要控制好A魔法的使用,优先队列加栈,x%3小的优先,x%3相等时,小的优先。

AC代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
using namespace std;

typedef long long LL;

const int MOD=1e9+7;

int n,m;

struct node
{
    int h;
    bool operator < (const node &b)const
    {
        return h%3<b.h%3 || (h%3==b.h%3 && h<b.h);
    }
};

int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        LL sum=0;
        LL ans=0;
        priority_queue<node> q;
        for(int i=0;i<n;i++)
        {
            node p;
            scanf("%d",&p.h);
            q.push(p);
            sum+=p.h/3+(p.h%3==0?0:1);
        }
        ans=sum%MOD;
        for(int i=1;i<=m;i++)
        {
            node x=q.top();
            q.pop();
            int num1=x.h/3+(x.h%3==0?0:1);
            x.h-=2;
            int num2;
            if(x.h>0)
                 num2=x.h/3+(x.h%3==0?0:1);
            else num2=0;
            if(x.h)  q.push(x);
            sum=sum-(num1-num2);
            ans=(ans+sum)%MOD;
        }
        printf("%lld\n",ans);
    }
}

  

xtu 1247  E题  Pair - pair

Pair-Pair

Bobo is tired of all kinds of hard LIS (Longest Increasing Subsequence) problems, so he decides to make himself some easier one.

Bobo has }.

It's clear that k.

Note that a sequence labeled with } only if:

  • n
  • k

Input

The input contains at most 30 sets. For each set:

The first line contains 3).

The m).

Output

For each set, ).

Sample Input

2 4
1 2
3 4
2 1
1 1
1 1

Sample Output

0 3 0 1
4 0 0 0
分析:开个1000*1000的数组,预处理矩阵和,然后分类讨论就好(借鉴他人)

AC代码:

#include <cstdio>
#include <iostream>
#include <ctime>
#include <vector>
#include <cmath>
#include <map>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long LL;
const int N=1e5+5;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
struct Node{
  int x,y;
}p[N];
int a[1005][1005];
int high[1005],low[1005],mid[1005];
LL ret[5];
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m)){
      memset(a,0,sizeof(a));
      memset(ret,0,sizeof(ret));
      memset(high,0,sizeof(high));
      memset(low,0,sizeof(low));
      memset(mid,0,sizeof(mid));
      for(int i=1;i<=n;++i){
         scanf("%d%d",&p[i].x,&p[i].y);
         ++a[p[i].x][p[i].y];
         if(p[i].y>p[i].x)++high[p[i].x];
         else if(p[i].y==p[i].x)++mid[p[i].x];
         else ++low[p[i].x];
      }
      for(int i=1;i<=m;++i){
        low[i]+=low[i-1];
        mid[i]+=mid[i-1];
        high[i]+=high[i-1];
      }
      for(int i=1;i<=m;++i)
        for(int j=1;j<=m;++j)
          a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1];
      for(int i=1;i<=n;++i){
        if(p[i].y>p[i].x){
             int tmp=0,t;
             t=high[m]-high[p[i].y];
             tmp+=t;ret[4]+=t;
             t=low[m]-low[p[i].y]+mid[m]-mid[p[i].y];
             tmp+=t;ret[3]+=t;
             t=high[p[i].y]-high[p[i].y-1];
             tmp+=t;ret[3]+=t;
             t=high[p[i].y-1]-high[p[i].x];
             tmp+=t;ret[3]+=t;
             t=a[p[i].x][m]-a[p[i].x][p[i].y];
             tmp+=t;ret[3]+=t;    
             ret[2]+=1ll*(n-tmp);
        }
        else if(p[i].x==p[i].y){
          int tmp=0,t;
          t=high[m]-high[p[i].x];
          tmp+=t;ret[3]+=t;
          t=low[p[i].x]+mid[p[i].x];
          tmp+=t;ret[1]+=t;
          ret[2]+=1ll*(n-tmp);
        }
        else {
          int tmp=0,t;
          t=low[p[i].y]+mid[p[i].y];
          tmp+=t;ret[1]+=t;
          t=high[m]-high[p[i].y];
          tmp+=t;ret[3]+=t;
          ret[2]+=1ll*(n-tmp);
        }
      }
      printf("%I64d %I64d %I64d %I64d\n",ret[1],ret[2],ret[3],ret[4]);
    }
    return 0;
}

 

xtu 1248  F题  Tc or CF
TC or CF

There are n contests going to be held in the upcoming year. However, the committee keeps debating whether the contest is of TC (Thinking Creatively) style or CF (Coding Fast) style.

The committee knows in advance that there are j.

If the 3 rules:

  • There are at least 1-st) should be TC-style.
  • There are also at least n-th) should be CF-style.
  • The total unhappiness of contestants is minimized.

Input

The input contains at most 30 sets. For each set:

The first line contains 500).

The 1000).

Output

For each set, an integer denotes the minimum of total unhappiness.

Sample Input

6 5
1 6 100
1 3 1
1 4 1
2 3 1
2 4 1
6 12
2 3 1
2 4 1
2 5 1
3 2 1
3 4 1
3 5 1
4 2 1
4 3 1
4 5 1
5 2 1
5 3 1
5 4 1

Sample Output

100
4

本题网上暂未找到AC代码 出题方题解
2016湖南湘潭邀请赛题解:2016年“长城信息”杯中国大学生程序设计比赛中南地区邀请赛(迟来的题解)

 


此题暂时无代码

 

 

xtu 1249  G题  Rolling Variance 

Rolling Variance

Bobo learnt that the variance of a sequence n is

1−−−−−−−−−−−−√

where

.

 

Bobo has a sequence }.

Input

The input contains at most 30 sets. For each set:

The first line contains ).

The second line contains 100).

Output

For each set, 1.

Your answer will be considered correct if its absolute or relative error does not exceed 4.

Sample Input

3 2
1 3 2
5 3
1 3 2 4 5

Sample Output

 

1.41421356
0.70710678
1.00000000
1.00000000
1.52752523

思路:前缀和

AC代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int M=100000+10;
double a[M],b[M];
int main()
{
    int n,m;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
     a[0]=b[0]=0;
     for(int i=1;i<=n;i++)
     {
        double x;
        scanf("%lf",&x);
        a[i]=a[i-1]+x;
        b[i]=b[i-1]+x*x;
     }

     for(int i=m;i<=n;i++)
     {
         double av=0,s=0;
         av=((a[i]-a[i-m])/(1.0*m));
         s=((b[i]-b[i-m])+m*av*av-2*av*(a[i]-a[i-m]))/(m-1);
         printf("%.8lf\n",sqrt(s));
     }
    }
    return 0;
}

  

xtu 1250  H题  Super Fast Fourier Transform 

Super Fast Fourier Transform

Bobo has two sequences of integers }. He would like to find

.

 

Note that x.

Input

The input contains at most 30 sets. For each set:

The first line contains 5).

The second line contains n.

The thrid line contains m.

(6)

Output

For each set, an integer denotes the sum.

Sample Input

1 2
1
2 3
2 3
1 2
3 4 5

Sample Output

2
7

思路:不同的数最多1000个,c++11交

AC 代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
const int M=1000000+10;
int  a[M],b[M],c[M],d[M];
typedef long long ll;
ll sum=0;
int main()
{
    int n,m;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
      memset(c,0,sizeof(c));
      memset(d,0,sizeof(d));
      int k1=0,k2=0;
      sum=0;
      for(int i=0;i<n;i++)
      {
          int x;
          scanf("%d",&x);
          c[x]++;
          if(c[x]==1) a[k1++]=x;
      }
      for(int i=0;i<m;i++)
      {
          int x;
          scanf("%d",&x);
          d[x]++;
          if(d[x]==1) b[k2++]=x;
      }
      for(int i=0;i<k1;i++)
      {
          for(int j=0;j<k2;j++)
          {
              ll x=(ll)sqrt(fabs(a[i]*1.0-b[j])*1.0);
              sum=sum+x*c[a[i]]*d[b[j]];
          }
      }
      printf("%lld\n",sum);
    }
    return 0;
}

 

xtu 1251  I题  Substring Query 

Substring Query

Given a string 2 kinds:

  1. to change the c;
  2. to query how many times does m.

Find out the result of each opeartion of the second kind.

Input

The input contains at most 10 sets. For each set:

The first line contains 5).

The second line contains a string n of lowercase characters.

The 4).

Output

For each operation of second kind in each set, an integer denotes the number of substrings.

Sample Input

5 5
aaaaa
0 aa
2 b
0 aba
4 b
0 aba
1 1
a
0 a

Sample Output

4
1
2
1

分析:AC自动机+分块

AC代码:

#include <bits/stdc++.h>
using namespace std ;

#define clr( a , x ) memset ( a , x , sizeof a )

const int MAXN = 100005 ;
const int MAXQ = 100005 ;
const int SQR1 = 128 ;
const int SQR2 = 256 ;

vector < int > G[MAXN] ;
char s[MAXN] , ss[MAXN] ;
string p[MAXQ] ;
int op[MAXQ] ;
int nxt[MAXN][26] , fail[MAXN] , idx[MAXN] , in[MAXN] , ou[MAXN] , point , root , dfs_clock ;
int c[1000] , val[MAXN] ;
int n , m ;
int Q[MAXN] , l , r ;

int newnode () {
    clr ( nxt[point] , 0 ) ;
    return point ++ ;
}

void init () {
    point = 0 ;
    root = newnode () ;
}

void insert ( string& s , int n , int id ) {
    int u = root ;
    for ( int i = 0 ; i < n ; ++ i ) {
        int x = s[i] - 'a' ;
        if ( !nxt[u][x] ) nxt[u][x] = newnode () ;
        u = nxt[u][x] ;
    }
    idx[id] = u ;
}

void dfs ( int u ) {
    in[u] = ++ dfs_clock ;
    for ( int i = 0 ; i < G[u].size () ; ++ i ) dfs ( G[u][i] ) ;
    ou[u] = dfs_clock ;
}

void build () {
    l = r = 0 ;
    fail[root] = root ;
    for ( int i = 0 ; i < 26 ; ++ i ) {
        if ( !nxt[root][i] ) nxt[root][i] = root ;
        else {
            fail[Q[r ++] = nxt[root][i]] = root ;
            G[root].push_back ( nxt[root][i] ) ;
        }
    }
    while ( l != r ) {
        int u = Q[l ++] ;
        for ( int i = 0 ; i < 26 ; ++ i ) {
            if ( !nxt[u][i] ) nxt[u][i] = nxt[fail[u]][i] ;
            else {
                fail[Q[r ++] = nxt[u][i]] = nxt[fail[u]][i] ;
                G[nxt[fail[u]][i]].push_back ( nxt[u][i] ) ;
            }
        }
    }
    dfs_clock = 0 ;
    dfs ( root ) ;
}

inline void add ( int x , int v ) {
    c[x / SQR2] += v ;
    val[x] += v ;
}

int sum ( int x , int y ) {
    int L = x / SQR2 + 1 ;
    int R = y / SQR2 - 1 ;
    int ans = 0 ;
    if ( R + 1 <= L ) {
        for ( int i = x ; i <= y ; ++ i ) {
            ans += val[i] ;
        }   
    } else {
        for ( int i = L ; i <= R ; ++ i ) {
            ans += c[i] ;
        }
        L *= SQR2 ;
        R *= SQR2 ;
        for ( int i = x ; i < L ; ++ i ) {
            ans += val[i] ;
        }
        for ( int i = R + SQR2 ; i <= y ; ++ i ) {
            ans += val[i] ;
        }
    }
    return ans ;
}

int getpos ( char s[] , int L , int R ) {
    int u = root ;
    for ( int i = L ; i < R ; ++ i ) {
        int x = s[i] - 'a' ;
        u = nxt[u][x] ;
    }
    return u ;
}

void addv ( char s[] , int L , int R , int v , int now ) {
    int u = now ;
    for ( int i = L ; i < R ; ++ i ) {
        int x = s[i] - 'a' ;
        u = nxt[u][x] ;
        add ( in[u] , v ) ;
    }
}

void get_fail ( char p[] , int m ) {
    fail[1] = 0 ;
    for ( int i = 2 , j = 0 ; i <= m ; ++ i ) {
        while ( j && p[i] != p[j + 1] ) j = fail[j] ;
        if ( p[i] == p[j + 1] ) ++ j ;
        fail[i] = j ;
    }
}

int kmp ( char s[] , int n , char p[] , int m ) {
    int ans = 0 ;
    for ( int i = 0 , j = 0 ; i < n ; ++ i ) {
        while ( j && s[i] != p[j + 1] ) j = fail[j] ;
        if ( s[i] == p[j + 1] ) {
            ++ j ;
            if ( j == m ) {
                ++ ans ;
                j = fail[j] ;
            }
        } else j = fail[j] ;
    }
    return ans ;
}

void solve () {
    init () ;
    for ( int i = 0 ; i < m ; ++ i ) {
        scanf ( "%d" , &op[i] ) ;
        cin >> p[i] ;
        if ( op[i] == 0 && p[i].length () <= SQR1 ) insert ( p[i] , p[i].length () , i ) ;
    }
    for ( int i = 0 ; i < point ; ++ i ) {
        G[i].clear () ;
    }
    build () ;
    clr ( c , 0 ) ;
    clr ( val , 0 ) ;
    addv ( s , 0 , n , 1 , root ) ;
    for ( int i = 0 ; i < m ; ++ i ) {
        if ( op[i] ) {
            -- op[i] ;
            int L = max ( 0 , op[i] - SQR1 ) , R = min ( n , op[i] + SQR1 ) ;
            int now = getpos ( s , L , op[i] ) ;
            addv ( s , op[i] , R , -1 , now ) ;
            s[op[i]] = p[i][0] ;
            addv ( s , op[i] , R , 1 , now ) ;
        } else {
            if ( p[i].length () > SQR1 ) {
                int len = 0 ;
                for ( int j = 0 ; j < p[i].length () ; ++ j ) {
                    ss[++ len] = p[i][j] ;
                }
                get_fail ( ss , len ) ;
                printf ( "%d\n" , kmp ( s , n , ss , len ) ) ;
            } else {
                int ans = sum ( in[idx[i]] , ou[idx[i]] ) ;
                printf ( "%d\n" , ans ) ;
            }
        }
    }
}

int main () {
    while ( ~scanf ( "%d%d%s" , &n , &m , s ) ) solve () ;
    return 0 ;
}

  

xtu 1252  J题  Defense Tower

Defense Tower

In ICPCCamp, there are i-th cities. It is guaranteed that cities are connected.

In the i itself.

Bobo would like to destroy all defense towers. When he tries to destroy the tower in city i will deal damage whose value equals to its power to Bobo.

Find out the minimum total damage Bobo will receive if he chooses the order to destroy the towers optimally.

Input

The input contains at most 30 sets. For each set:

The first line contains an integer 5).

The second line contains 4).

The n).

Output

For each set, an integer denotes the minimum total damage.

Sample Input

3
1 2 3
1 2
2 3
3
1 100 1
1 2
2 3

Sample Output

3
2

思路:考虑每条边对玩家的伤害

         假设连接的节点是u,v,破坏力是p[u]和p[v]

         假设p[u]>p[v]

         现在考虑u,v的删除顺序,如果先删u,这条边对玩家的伤害,是p[v],先删v,伤害是p[u]

         所以显然对于每条边,我们都要先删权值大的,才能最好

         怎么样才能对于每条边先删最大的呢,那就按照权值递减删就好了

         所以 ret=Σ(min(p[u],p[v]))

        复杂度O(n)

AC代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
const int M=100000+10;
int p[M];
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
     int sum=0;
     for(int i=1;i<=n;i++)
     {
         scanf("%d",&p[i]);
     }

     for(int i=1;i<n;i++)
     {
         int x,y;
         scanf("%d %d",&x,&y);
         sum+=min(p[x],p[y]);
     }
     printf("%d\n",sum);
    }
    return 0;
}

  

 

---恢复内容结束---

相关文章:

  • 2022-12-23
  • 2022-02-20
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-06-27
  • 2022-12-23
  • 2021-10-19
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-10-04
  • 2022-12-23
  • 2021-06-25
  • 2022-01-29
相关资源
相似解决方案