zoukankan      html  css  js  c++  java
  • TZOJ 挑战题库随机训练11

    点击题号跳转

    A3604 B5608 C5385 D5003 E2527

    F2108 G4712 H3993 I1892 J3842

    A.The Table回到顶部

    题意

    n行m列,问哪一列乘积最大,相同输出m大的,n<=1000,m<=20

    题解

    曾经做过(07G),大数相乘处理一下就行了,复杂度O(nm)

    代码

     1 import java.math.BigInteger;
     2 import java.util.*;
     3 
     4 public class Main {
     5 
     6     public static void main(String[] args) {
     7 
     8         BigInteger[] big = new BigInteger[25];
     9 
    10         Scanner sc = new Scanner(System.in);
    11         while(sc.hasNext()) {
    12             int m = sc.nextInt();
    13             int n = sc.nextInt();
    14             BigInteger b;
    15             for (int i = 1; i <= m; i++)
    16                 big[i] = BigInteger.ONE;
    17             for (int i = 1; i <= n; i++) {
    18                 for (int j = 1; j <= m; j++) {
    19                     b = sc.nextBigInteger();
    20                     big[j] = big[j].multiply(b);
    21                 }
    22             }
    23             int id = 1;
    24             BigInteger maxx = big[1];
    25             for (int i = 2; i <= m; i++) {
    26                 //System.out.println(maxx.compareTo(big[i]));
    27                 if (maxx.compareTo(big[i]) <= 0) {
    28                     maxx = big[i];
    29                     id = i;
    30                 }
    31             }
    32             System.out.println(id);
    33         }
    34     }
    35 }
    A

    B.单身狗沙漠逃生回到顶部

    题意

    每走x公里路后,单身狗就要消耗x份食物(x为大于0的分数)。单身狗共准备了n份食物,但他身上最多背负m份食物(n%m为0,而且n/m<11)。如果食物可以在路边存放,为保证能原路返回出发点,单身狗最远能进入沙漠多少公里?

    题解

    一共走m/n次,第一次(来回)m/2,第二次m/4,以此类推,复杂度O(m/n)

    代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 int main(){
     5     int n,m;
     6     while(cin>>n>>m,n||m){
     7         int s=0,x=2*2520;
     8         for(int i=1;i<=n/m;i++)s+=m*(2520/i);
     9         int gc=__gcd(s,x);
    10         cout<<s/gc<<'/'<<x/gc<<endl;
    11     }
    12     return 0;
    13 }
    B

    C.树的遍历回到顶部

    题意

    给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数,n<=30

    题解

    后序(左右根),中序(左根右)

    递归建树,后序第一个节点为根,然后在中序找到这个根,左右子树分开,复杂度O(n)

    代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int N=1005;
     5 int a[N],b[N];
     6 vector<int>G[35];
     7 void build(int L1,int R1,int L2,int R2,int dep){
     8     if(L1>R1)return;
     9     G[dep].push_back(a[R1]);
    10     for(int i=L2;i<=R2;i++)if(a[R1]==b[i]){
    11         build(L1,L1-1-L2+i,L2,i-1,dep+1);
    12         build(R1-R2+i,R1-1,i+1,R2,dep+1);
    13     }
    14 }
    15 int main(){
    16     int n;scanf("%d",&n);
    17     for(int i=1;i<=n;i++)cin>>a[i];
    18     for(int i=1;i<=n;i++)cin>>b[i];
    19     build(1,n,1,n,0);
    20     int out=0;
    21     for(int i=0;i<30;i++)for(int j=0;j<G[i].size();j++){
    22         if(out)cout<<' ';
    23         cout<<G[i][j];out=1;
    24     }
    25     return 0;
    26 }
    C

    D.Convert QWERTY to Dvorak回到顶部

    题意

    给一串键盘A要求输出键盘B,len<=100

    题解

    对应映射存起来,再处理,复杂度O(70len)

    代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 string a="-=_+qwertyuiop[]QWERTYUIOP{}asdfghjkl;'ASDFGHJKL:"zxcvbnm,./ZXCVBNM<>?";
     5 string b="[]{}',.pyfgcrl/="<>PYFGCRL?+aoeuidhtns-AOEUIDHTNS_;qjkxbmwvz:QJKXBMWVZ";
     6 int main(){
     7     string s;
     8     while(getline(cin,s)){
     9         for(int i=0;s[i];i++){
    10             bool f=0;
    11             for(int j=0;a[j];j++)
    12                 if(s[i]==a[j]){
    13                     f=1;cout<<b[j];
    14                 }
    15             if(f==0)cout<<s[i];
    16         }
    17         cout<<endl;
    18     }
    19     return 0;
    20 }
    D

    E.Formula Racing回到顶部

    题意

    给一张n*m的图,W代表墙,s代表起跑线/目标线,.代表非跑道,x代表跑道

    d辆车,给你起点方向和最大速度,在给一串操作序列

    m代表前进,a代表速度+1再前进,b代表速度-1再前进,l代表左转再前进,r代表右转再前进

    如果小车到了.,速度降为1

    每辆车输出,如果到了s,输出crossing startline

    如果小车没有撞墙输出终点方向速度

    如果小车撞墙了就停止crashed

    n,m<=1000,d<=7,len<=10000

    题解

    模拟每辆小车的操作,按照要求处理,复杂度O(sumlend)

    坑1:注意n行m列,列代表y,行代表x,在判断的时候判断的是G[y][x]

    坑2:如果小车最后撞墙,之前如果经过s也要输出crossing startline

    PS:题意有点难理解

    代码

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<vector>
     4 using namespace std;
     5 
     6 const int N=1005;
     7 
     8 char G[N][N];
     9 int dx[]={0,1,1,1,0,-1,-1,-1};
    10 int dy[]={-1,-1,0,1,1,1,0,-1};
    11 struct node{
    12     int ux,uy,dir,sp,i;
    13 };
    14 int main(){
    15     int t,n,m,q;
    16     scanf("%d",&t);
    17     for(int ca=1;ca<=t;ca++){
    18         scanf("%d%d",&n,&m);
    19         for(int i=0;i<n;i++)scanf("%s",G[i]);
    20         scanf("%d",&q);
    21         printf("Scenario #%d:
    ",ca);
    22         while(q--){
    23             int ux,uy,dir,spm,sp=0;char op[10005];
    24             scanf("%d%d%d%d%s",&ux,&uy,&dir,&spm,op);
    25             //printf("%d %d %d %d %s
    ",ux,uy,dir,spm,op);
    26             vector<node>vec;
    27             int len=strlen(op);
    28             for(int i=0;i<len;i++){
    29                 if(op[i]=='a'&&sp<spm)sp++;
    30                 if(op[i]=='b'&&sp>0)sp--;
    31                 if(op[i]=='l')dir=(dir+7)%8;
    32                 if(op[i]=='r')dir=(dir+1)%8;
    33                 int up=0;
    34                 for(int j=1;j<=sp;j++){
    35                     ux+=dx[dir],uy+=dy[dir];
    36                     //printf("j=%d ux=%d uy=%d
    ",j,ux,uy);
    37                     if(G[uy][ux]=='W'){
    38                         printf("%d %d %d %d crashed
    ",ux,uy,dir,sp);
    39                         goto e;
    40                     }
    41                     if(G[uy][ux]=='.')up=1;
    42                     if(G[uy][ux]=='s')vec.push_back((node){ux,uy,dir,sp,i});
    43                 }
    44                 //printf("i=%d (%d,%d) dir=%d sp=%d
    ",i,ux,uy,dir,sp);
    45                 if(up)sp=1;
    46             }
    47             printf("%d %d %d %d
    ",ux,uy,dir,sp);
    48             e:;
    49             for(int i=0;i<vec.size();i++)
    50                 printf("crossing startline: %d %d %d %d %d
    ",vec[i].ux,vec[i].uy,vec[i].dir,vec[i].sp,vec[i].i);
    51         }
    52         printf("
    ");
    53     }
    54     return 0;
    55 }
    E

    F.Helping Florida回到顶部

    题意

    n个候选人,m张选票,每轮选举淘汰票数最少的(可以有多个最少),对于选票来说如果这个候选人被淘汰,那么就推到下一个候选人

    选票的结构是,候选人1,候选人2,候选人3......

    到最后一轮或者候选者有>=(m+1)/2张票,对应的候选者获胜,可以有多个获胜

    题解

    模拟每轮被淘汰的候选人,注意处理选票的时候不要越界了,复杂度O(nm)

    PS:唯一获胜XXX won,并列获胜it is a tie between XXX and XXX

    PS:题意又是有点难理解

    代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 map<string,int>votes;
     5 vector<string>vec[105];
     6 int tail[105];
     7 int main(){
     8     ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
     9     int n,m;string s,ss;
    10     while(cin>>n>>m,n||m){
    11         votes.clear();
    12         for(int i=1;i<=m;i++)vec[i].clear(),tail[i]=0;
    13         cin.get();
    14         for(int i=1;i<=m;i++){
    15             getline(cin,ss);
    16             stringstream s(ss);
    17             while(s>>ss)vec[i].push_back(ss);
    18         }
    19         map<string,int>dead;
    20         for(int i=1;i<=m;i++)votes[vec[i][0]]++;
    21         int t=0,MinVo,MaxVo;
    22         while(1){
    23             MinVo=1e9;MaxVo=0;
    24             for(auto X:votes)MinVo=min(MinVo,X.second),MaxVo=max(MaxVo,X.second);
    25             if(MaxVo>=(m+1)/2){
    26                 t=1;
    27                 break;
    28             }
    29             vector<string>del;
    30             for(auto X:votes)if(MinVo==X.second)del.push_back(X.first);
    31             if(del.size()==votes.size())break;
    32             for(auto X:del){
    33                 dead[X]=1,votes.erase(X);
    34             }
    35             int rup=0;
    36             for(int i=1;i<=m;i++){
    37                 int up=0;
    38                 while(tail[i]<vec[i].size()&&dead.count(vec[i][tail[i]]))tail[i]++,up=1;
    39                 if(tail[i]<vec[i].size()&&up)rup=1,votes[vec[i][tail[i]]]++;
    40             }
    41             if(rup==0)break;
    42         }
    43         vector<string>out;
    44         if(t){
    45             for(auto X:votes)if(X.second==MaxVo)out.push_back(X.first);
    46         }
    47         else{
    48             for(auto X:votes)out.push_back(X.first);
    49         }
    50         if(out.size()==1)cout<<out[0]<<" won
    ";
    51         else{
    52             cout<<"it is a tie between "<<out[0];
    53             for(int i=1;i<out.size();i++)
    54                 cout<<" and "<<out[i];
    55             cout<<'
    ';
    56         }
    57     }
    58     return 0;
    59 }
    F

    G.Double Shortest Paths回到顶部

    题意

    给一张有向图,边(u,v,a,b)第一次经过花费a,第二次经过花费a+b,问从1->n走两次的最小花费,n<=500,m<=2000

    题解

    最小费用最大流模板题,超级源点S(0)->1流量2花费0,n->超级汇点T(n+1)流量2花费0,其余(u,v,a,b),连两条,第一条u->v流量1花费a,第二条u->v流量1花费a+b,复杂度玄学(一般n<=500)

    代码

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 
      4 const int N=1e5+5;
      5 const int M=2e5+5;
      6 const int INF=0x3f3f3f3f;
      7 
      8 int FIR[N],FROM[M],TO[M],CAP[M],FLOW[M],COST[M],NEXT[M],tote;
      9 int pre[N],dist[N],q[400000];
     10 bool vis[N];
     11 int n,m,S,T;
     12 void init()
     13 {
     14     tote=0;
     15     memset(FIR,-1,sizeof(FIR));
     16 }
     17 void addEdge(int u,int v,int cap,int cost)
     18 {
     19     FROM[tote]=u;
     20     TO[tote]=v;
     21     CAP[tote]=cap;
     22     FLOW[tote]=0;
     23     COST[tote]=cost;
     24     NEXT[tote]=FIR[u];
     25     FIR[u]=tote++;
     26 
     27     FROM[tote]=v;
     28     TO[tote]=u;
     29     CAP[tote]=0;
     30     FLOW[tote]=0;
     31     COST[tote]=-cost;
     32     NEXT[tote]=FIR[v];
     33     FIR[v]=tote++;
     34 }
     35 bool SPFA(int s, int t)//寻找花销最少的路径
     36 {
     37     //跑一遍SPFA 找s——t的最少花销路径 且该路径上每一条边不能满流
     38     //若存在 说明可以继续增广,反之不能
     39     memset(dist,INF,sizeof(dist));
     40     memset(vis,false,sizeof(vis));
     41     memset(pre,-1,sizeof(pre));
     42     dist[s] = 0;vis[s]=true;q[1]=s;
     43     int head=0,tail=1;
     44     while(head!=tail)
     45     {
     46         int u=q[++head];vis[u]=false;
     47         for(int v=FIR[u];v!=-1;v=NEXT[v])
     48         {
     49             if(dist[TO[v]]>dist[u]+COST[v]&&CAP[v]>FLOW[v])//可以松弛 且 没有满流
     50             {
     51                 dist[TO[v]]=dist[u]+COST[v];
     52                 pre[TO[v]]=v;//记录前驱边 的编号
     53                 if(!vis[TO[v]])
     54                 {
     55                     vis[TO[v]] = true;
     56                     q[++tail]=TO[v];
     57                 }
     58             }
     59         }
     60     }
     61     return pre[t]!=-1;//可达返回true
     62 }
     63 void MCMF(int s, int t, int &cost, int &flow)
     64 {
     65     flow=0;//总流量
     66     cost=0;//总费用
     67     while(SPFA(s,t))//每次寻找花销最小的路径
     68     {
     69         int Min = INF;
     70         //通过反向弧 在源点到汇点的最少花费路径 找最小增广流
     71         for(int v=pre[t];v!=-1;v=pre[TO[v^1]])
     72             Min = min(Min, CAP[v]-FLOW[v]);
     73         //增广
     74         for(int v=pre[t];v!=-1;v=pre[TO[v^1]])
     75         {
     76             FLOW[v]+=Min;
     77             FLOW[v^1]-=Min;
     78             cost+=COST[v]*Min;//增广流的花销
     79         }
     80         flow+=Min;//总流量累加
     81     }
     82 }
     83 int main(){
     84     int ca=0;
     85     while(scanf("%d%d",&n,&m)!=EOF){
     86         init();
     87         for(int i=0,u,v,d,a;i<m;i++){
     88             scanf("%d%d%d%d",&u,&v,&d,&a);
     89             addEdge(u,v,1,d);
     90             addEdge(u,v,1,d+a);
     91         }
     92         S=0,T=n+1;
     93         addEdge(S,1,2,0);
     94         addEdge(n,T,2,0);
     95         int cost,flow;
     96         MCMF(S,T,cost,flow);
     97         printf("Case %d: %d
    ",++ca,cost);//最小费用 最大流
     98     }
     99     return 0;
    100 }
    G

    H.Discrepancies in the Voters List回到顶部

    题意

    给n1,n2,n3个数,问出现>=2的数,n1,n2,n3<=50000

    题解

    map哈希求次数>=2,复杂度O(sumnlog(sumn))

    PS:题意也没说会不会出现相同的,没有相同的话上面这么做

    PS:如果有相同的话,处理map<int,int>f[3]判断是否都有

    代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 map<int,int>ma;
     5 int main(){
     6     int n1,n2,n3,x;
     7     scanf("%d%d%d",&n1,&n2,&n3);
     8     for(int i=1;i<=n1;i++)scanf("%d",&x),ma[x]++;
     9     for(int i=1;i<=n2;i++)scanf("%d",&x),ma[x]++;
    10     for(int i=1;i<=n3;i++)scanf("%d",&x),ma[x]++;
    11     int cnt=0;
    12     for(auto X:ma)if(X.second>=2)cnt++;
    13     printf("%d
    ",cnt);
    14     for(auto X:ma)if(X.second>=2)printf("%d
    ",X.first);
    15     return 0;
    16 }
    H

    I.Optimal Programs回到顶部

    题意

    求一个操作序列,ADD,SUB,MUL,DIV分别是从栈顶取出两个再做对应操作,DUP是复制栈顶元素

    f(x)=y代表栈初始值x,经过操作序列操作后,得到最后的值为y,要求对于每个x[i]都可以推出y[i]

    n<=10,答案操作序列<=10

    题解

    最暴力的做法是5^10*10*10肯定不行,需要优化,这里优化的东西挺多的

    优化1:如果当前序列存在除0,栈顶弹不出2个,这个序列就不用搜索下去了

    优化2:如果最后栈的大小不为1,f(x[i])!=y[i]可以快速判断非法,可以继续搜索

    优化3:如果所有x[i]=y[i]那么直接输出Empty sequence

    优化4:初始只有一个x[i],那么第一次操作一定为DUP

    复杂度O(<<5^9*10*10)

    PS:又是一道特别难理解的题,淦

    代码

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 
      4 //0 ADD
      5 //1 DUP
      6 //2 DIV
      7 //3 MUL
      8 //4 SUB
      9 int f,path[10],x[10],y[10],n;
     10 char out[5][5]={"ADD","DIV","DUP","MUL","SUB"};
     11 struct node{
     12     int path[10];
     13     int p;
     14 };
     15 //check=0序列不合法,1序列合法答案不合法,2序列合法答案合法
     16 int check(node v){
     17     //for(int i=0;i<=v.p;i++)printf("%d ",v.path[i]);
     18     //puts("");
     19     for(int i=0;i<n;i++){
     20         stack<int>st;
     21         st.push(x[i]);
     22         int a,b;
     23         for(int j=0;j<=v.p;j++){
     24             if(v.path[j]==0){
     25                 if(!st.empty())a=st.top(),st.pop();
     26                 else return 0;
     27                 if(!st.empty())b=st.top(),st.pop();
     28                 else return 0;
     29                 if(a+b<-30000||a+b>30000)return 0;
     30                 else st.push(a+b);
     31             }else if(v.path[j]==1){
     32                 if(!st.empty())a=st.top(),st.pop();
     33                 else return 0;
     34                 if(!st.empty())b=st.top(),st.pop();
     35                 else return 0;
     36                 if(a==0)return 0;
     37                 else if(b/a<-30000||b/a>30000)return 0;
     38                 else st.push(b/a);
     39             }else if(v.path[j]==2){
     40                 if(!st.empty())a=st.top();
     41                 else return 0;
     42                 st.push(a);
     43             }else if(v.path[j]==3){
     44                 if(!st.empty())a=st.top(),st.pop();
     45                 else return 0;
     46                 if(!st.empty())b=st.top(),st.pop();
     47                 else return 0;
     48                 if(a*b<-30000||a*b>30000)return 0;
     49                 else st.push(a*b);
     50             }else if(v.path[j]==4){
     51                 if(!st.empty())a=st.top(),st.pop();
     52                 else return 0;
     53                 if(!st.empty())b=st.top(),st.pop();
     54                 else return 0;
     55                 if(b-a<-30000||b-a>30000)return 0;
     56                 else st.push(b-a);
     57             }
     58         }
     59         if(st.size()!=1)return 1;
     60         else if(st.top()!=y[i])return 1;
     61     }
     62     return 2;
     63 }
     64 void bfs(){
     65     queue<node>q;
     66     node s;
     67     s.path[0]=2;s.p=0;
     68     q.push(s);
     69     while(!q.empty()){
     70         node u=q.front();q.pop();
     71         for(int i=0;i<=4;i++){
     72             if(u.p+1<=9){
     73                 node v=u;
     74                 v.path[u.p+1]=i;v.p++;
     75                 int oo=check(v);
     76                 if(oo==1)q.push(v);
     77                 else if(oo==2){
     78                     for(int j=0;j<=v.p;j++)path[j]=v.path[j];
     79                     f=v.p;return;
     80                 }    
     81             }
     82         }
     83     }
     84 }
     85 int main(){
     86     int ca=1;
     87     while(scanf("%d",&n)!=EOF,n){
     88         for(int i=0;i<n;i++)scanf("%d",&x[i]);
     89         for(int i=0;i<n;i++)scanf("%d",&y[i]);
     90         int same=1;
     91         for(int i=0;i<n;i++)if(x[i]!=y[i])same=0;
     92         //5^10=9e6
     93         printf("Program %d
    ",ca++);
     94         if(same){
     95             printf("Empty sequence
    
    ");
     96             continue;
     97         }
     98         f=-1;
     99         bfs();
    100         if(f>-1){
    101             printf("%s",out[path[0]]);
    102             for(int i=1;i<=f;i++)
    103                 printf(" %s",out[path[i]]);
    104             printf("
    ");
    105         }
    106         else printf("Impossible
    ");
    107         puts("");
    108     }
    109     return 0;
    110 }
    I

    J.Bovine Bridge Battle回到顶部

    题意

    n个点,问多少个4元组两两对称,n<=1000

    题解

    求出每两个点的中点,统计次数,为了防止出现小数,可以先*2

    然后遍历所有中点,可以发现就是C(n,2),复杂度O(2n^2logn)

    PS:可以把pair<int,int>hash成一个long,然后存在unordered中可以少个log,复杂度O(n^2)

    代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define LL long long
     5 
     6 const int N=1005;
     7 
     8 int x[N],y[N];
     9 map<pair<int,int>,int>ma;
    10 
    11 int main(){
    12     int n;
    13     scanf("%d",&n);
    14     for(int i=1;i<=n;i++)scanf("%d%d",&x[i],&y[i]);
    15     for(int i=1;i<=n;i++)x[i]<<=1,y[i]<<=1;
    16     for(int i=1;i<=n;i++)for(int j=1;j<i;j++){
    17         int x1=(x[i]+x[j])/2;
    18         int y1=(y[i]+y[j])/2;
    19         ma[{x1,y1}]++;
    20     }
    21     LL ans=0;
    22     for(auto X:ma)ans+=(1LL*X.second*(X.second-1))/2;
    23     printf("%lld",ans);
    24     return 0;
    25 }
    J
  • 相关阅读:
    计算机网络 其他1
    C++ part9
    C++ part8
    操作系统 part5
    C++ part7
    MyXls导出Excel的各种设置
    C# excel操作
    Castle
    C# Keycode对照表
    IEnumerable.Select和SelectMany的区别
  • 原文地址:https://www.cnblogs.com/taozi1115402474/p/12818066.html
Copyright © 2011-2022 走看看