HPU第一次团队赛

五迷三道 提交于 2019-11-28 06:14:16

D. Tom的战力问题

Tom揍了TAT。
Tom下定决心要战胜
但是在战胜最强的之前,Tom要先打败其他的狗。为此,他打算先收集一下信息。
现在Tom在了得到了一些关于战斗力的小道消息,例如X号狗狗的战力比Y号狗狗的战力高S点。
Tom想知道利用这些消息,能不能判断出某两只狗之间的战力高低?高多少?

输入格式

第一行包含三个整数N,MQN表示狗总数,M表示Tom知道消息的总数,Q表示小Tom想询问的数量。  

以下M行每行三个整数,X,YS。表示X号狗的战力比Y号狗的战力高S点。  

以下Q行每行两个整数,XY。表示Tom想知道X号狗的战力比Y号狗的战力高几点。  
2N1000 
1M,QN 
1X,YN 
1000S1000

数据保证没有矛盾。

输出格式

对于每个询问,如果不能判断出XY高几点输出1。否则输出XY高多少战力点。

样例

input
10 5 3  1 2 10  2 3 10  4 5 -10  5 6 -10  2 5 10  1 10  1 5  3 5  
output
-1  20  0其实就是一个简单的BFS问题。题目中问两个狗之间的站力相差多少,我们可以看成路径问题即A到B的距离为C,B到A的距离为-C,然后跑图,不可到大的话输出-1
 #include<iostream>  #include<cstdio>  #include<cstring>  #include<vector>  #include<queue>  using namespace std;  const int N=1e3+7;  int n,m,q;    struct stu{      int a,b;  };  vector<stu >ve[N];  int mark[N];  bool check=false ;  int f=-1;    void bfs(int x,int y){      memset(mark,0,sizeof(mark));      queue<stu >que;      que.push({x,0});      mark[x]=1;      while(que.size()){          stu aa=que.front();          que.pop();  //        cout<<aa.a<<endl;          if(aa.a==y){              f=aa.b;              break;          }          for(int i=0;i<ve[aa.a].size();i++){              if(mark[ve[aa.a][i].a]==0){                  mark[ve[aa.a][i].a]=1;                  que.push({ve[aa.a][i].a,aa.b+ve[aa.a][i].b});              }          }      }  }      int main(){      scanf("%d%d%d",&n,&m,&q);      int x,y,z;            for(int i=1;i<=m;i++){          scanf("%d%d%d",&x,&y,&z);          ve[x].push_back({y,z});          ve[y].push_back({x,-z});      }                  while(q--){           f=-1;           int x,y;           scanf("%d%d",&x,&y);           bfs(x,y);           printf("%d\n",f);      }             return 0;  } 

E  Tom的函数求值

众所周知,Tom不会递归,但是今天他突然顿悟了!并且凭借自己的能力写出了下面这段代码:

int F(int m,int n)  {      if(!m)          return n+1;      if(!n&&m)          return F(m-1,1);      if(m&&n)          return F(m-1,F(m,n-1));  }  

现在,他想让你根据这个函数来解决问题

输入格式

单组输入,每组一行,有两个整数mn(0m3,0n27)

输出格式

请输出上面代码的运行结果

样例

input
1 1  
output
3  
input
0 1  
output
2  

提示

如果不知道怎么做的话,不妨试试直接把代码复制粘贴进去吧٩̋(ˊ•͈ ꇴ •͈ˋ)و

对于这种类型的题目,我们可以先运行一下它给出的代码,然后输出一些值,在找规律。

//int F(int m,int n)  //{  //    if(!m)  //        return n+1;  //    if(!n&&m)  //        return F(m-1,1);  //    if(m&&n)  //        return F(m-1,F(m,n-1));  //}  #include<iostream>  #include<cstdio>  using namespace std;  typedef long long ll;  // m==0  n+1;  // m==1  2 3 4  // m==2  3 5 7  // m==3  5 13 29  ll f(ll x){      if(x==0) return 5;      else return 2*f(x-1)+3;  }  int main(){      ll a,b;      scanf("%lld %lld",&a,&b);      if(a==0) printf("%d",b+1);      else if(a==1) printf("%d\n",b+2);      else if(a==2) printf("%d\n",2*b+3);       else if(a==3) printf("%lld\n",f(b));      return 0;  } 

FTom的约会

XX协会又要迎来新的成员了。

这次的妹子颇多,足足有n人之多(1n106),她们每个人的学号都是1018 内的一个正整数。

Jerry 早早地就掌握了她们每个人的学号,并且知道她们之中有一个人和Tom约会去了!

Jerry 统计了在场所有妹子的学号,他想知道,哪个人没来?

输入格式

第一行是一个整数n,代表一共有n只妹纸

以下n行每行一个整数,代表每只妹纸的学号

接下来一个空行

以下n1行每行一个整数,代表每只来了的妹纸的学号

输出格式

输出没来的妹纸的学号。

样例

input
3  10061061  10061023  10061201    10061023  10061201  
output
10061061  

提示

开头别想着抢一血,稳着跟榜做题,很多队伍过的题自己卡住了别慌,肯定不是特别难的算法,多换几个思路,上个厕所调整一下状态,总之,心态要好~
~~ 以上都是废话 ~~

看到这个题目,觉得用map比较好,但是TLE了,,用map没TLE的是卡过去的,这里可以开个两个数组,存完值后进行排序,找到第一个不向等的,就可以退出了,

也可以用无序字典

代码1:

#include<iostream>  #include<cstdio>  #include<unordered_map>  using namespace std;  typedef long long ll;  unordered_map<ll,int >mp;  unordered_map<ll,int>::iterator it;  int main(){      int t;      cin>>t;      int t1=t-1;      while(t--){          ll x1;          scanf("%lld",&x1);          mp[x1]++;      }      while(t1--){          ll y;          scanf("%lld",&y);          mp[y]++;      }      for(it=mp.begin();it!=mp.end();it++){          if(it->second==1){              printf("%lld\n",it->first);              break;          }       }      return 0;  } 

代码2:

#include<cstdio>  #include<algorithm>   #include<vector>  using namespace std;  typedef long long ll;   const int     N=1e6+7;  ll p[N];  ll p2[N];  int main(){      int t;      scanf("%d",&t);      ll x;      for(int i=1;i<=t;i++){          scanf("%lld",&p[i]);      }      for(int i=1;i<=t-1;i++){          scanf("%lld",&p2[i]);      }      sort(p+1,p+1+t);      sort(p2+1,p2+t);      bool f=false ;      for(int i=1;i<=t-1;i++){          if(p[i]!=p2[i]){              f=true;              printf("%lld",p[i]);              break;           }      }      if(!f) printf("%lld",p[t]);                  return 0;  } 

G. Tom爬楼梯

Jerry 跑到了二楼,现在Tom面临的是一个n阶的楼梯,由于Tom的腿比较短,因此它一次只能爬1阶或2阶,机智的Jerry破坏掉了m阶楼梯,也就是说Tom无法踩在这m阶楼梯上,现在Tom想知道他有多少种方案能爬到第n阶楼梯。由于答案很大,输出方案数对109+7取模的结果。

输入格式

第一行输入一个T代表有T组输入,对于每组输入:
第一行输入n,m,第二行输入m个数,第i个数ai代表第ai阶楼梯被破坏了。
(1T,m10,1n1000,1ain)

输出格式

对于每组输入,输出方案数对109+7取模的结果。

样例

input
3  1 1  1  8 1  1  10 2  1 2  
output
0  13  0  
 被这个题卡了好久,一开始的想法是计算每一个阶段的值,然后再相乘,但是不好写。。而且数据很大。。
题解:用两个数组,第一个记录每个坏掉的楼梯,第一个记录两个楼梯之间正常楼梯的个数,这里注意开头要特殊处理。开头要保存正常楼梯个数加1。
递推式:dp[1]=1,dp[2]=1.dp[n]=dp[n-1]+dp[n-2];
#include<bits/stdc++.h>  using namespace std;  typedef long long ll;  const int mod=1e9+7;    ll dp[1000+7];  ll arr[1000+7];  ll arr2[1000+7];    void inint(){      dp[1]=1;      dp[2]=1;      for(int i=3;i<=1000;i++){          dp[i]=(dp[i-1]%mod+dp[i-2]%mod)%mod;       }  }    int main(){      inint();      int t;      cin>>t;      while(t--){          ll a,b1;          scanf("%lld%lld",&a,&b1);          for(int i=1;i<=b1;i++){              scanf("%lld",&arr[i]);          }          sort(arr+1,arr+1+b1);  //         if(arr[b1]==a){  //             puts("0");  //             continue ;  //         }          int pos=0;          arr2[pos++]=arr[1];          for(int i=2;i<=b1;i++){              arr2[pos++]=arr[i]-arr[i-1]-1;          }          arr2[pos++]=a-arr[b1];          ll ans=1;          for(int i=0;i<pos;i++){              ans=(ans%mod*dp[arr2[i]]%mod)%mod;          }          cout<<ans<<endl;      }            return 0;  }

I. Jerry的数学题

Tom自称是数学天才,无法忍受的Jerry 给 Tom 出了一道题,已知a,b,求解下列方程:

{lcm(x,y)=agcd(x,y)=b

Tom顿时傻眼了,现在只有你能来帮他挽回颜面了,快来帮帮它吧。

 

输入格式

第一行输入一个T代表有T组输入。
每组输入包含两个正整数a,b
(1T100,1a,b10000)

输出格式

对于每组输入,每行输出一组x,y,如果有多组,则输出x最小的,x,y中间用空格隔开。如果无解输出1

样例

input
3  100 50  3 3  6 7  
output
50 100  3 3  -1
#include<bits/stdc++.h>  using namespace std;    int main(){      int t;      scanf("%d",&t);      while(t--){          int a,b;          scanf("%d%d",&a,&b);          int x=a*b;          bool check=false ;          for(int i=b;i<=a;i+=b){              int y=x/i;              if(x%i==0&&__gcd(i,y)==b){                  check=true;                  if(y<i) swap(y,i);                  printf("%d %d\n",i,y);                  break ;               }          }          if(!check) puts("-1");      }            return 0;  }

J. Jerry的题

Jerry给Tom出了一道题,题目是这样的:
**给出一棵n个节点的树,节点编号为1-n(根节点编号为1),每一个节点作为根节点与他所有的子孙节点形成一棵子树,而这棵子树包含节点的数量,称作子树的Size。

例如:

1─2─4─5
└─3

其中节点5的子树只包括节点5,Size = 1。节点4的子树包括节点4,5,Size = 2。节点1的子树包括节点1,2,3,4,5,Size = 5。

求以所有节点为根的子树的Size之和。上面例子中,节点1到5,对应的Size分别为5,3,1,2,1,所有Size的和 = 5 + 3 + 1 + 2 + 1 = 12

输入格式

第一行:1个数n(1 < n <= 10000),表示树的节点数量。
后面n-1行:每行2个数x y,表示节点x是节点y的父节点(1 <= x, y <= n)。

输出格式

输出1个数,表示以所有节点为根的子树的Size之和。

样例

input
4  1 2  1 3  2 4  
output
8  
 这个题目也是一个简单的BFS,我们只要记录每个点可以到达的 点的个数就可以了
#include<iostream>  #include<cstdio>  #include<cstring>  #include<vector>  #include<queue>  using namespace std;  const int N=1E5+7;  vector<int >ve[N];  int step[N];  bool mark[N];  int ans=1;  void bfs(int x){      memset(mark,0,sizeof(mark));      queue<int>que;      que.push(x);      mark[x]=1;      step[x]=0;  //    cout<<"x:"<<x<<endl;      while(que.size()){          int t=que.front();          que.pop();           for(int i=0;i<ve[t].size();i++){  //            cout<<ve[t][i]<<"++"<<endl;  //            ans++;              if(mark[ve[t][i]]==0){                  ans++;                   mark[ve[t][i]]=1;                  step[ve[t][i]]=step[t]+1;                  que.push(ve[t][i]);              }          }      }  }      int main(){      int t;      cin>>t;       int x,y;      for(int i=1;i<=t-1;i++)      {          cin>>x>>y;          ve[x].push_back(y);      }      long long sum=0;      for(int i=1;i<=t;i++){          ans=1;          bfs(i);          sum+=1ll*ans;      }      cout<<sum<<endl;      return 0;  }

 

L. Jerry的食粮

公元9102年,Tom不再追逐Jerry,因为Tom的主人已经从China进口了很多猫粮,并且还有了智能抓老鼠机器。
Jerry无处可躲,只能露宿街头。Tom不再缺乏食粮,但是可怜的小Jerry仍然还饥肠辘辘。
这一天,小Jerry实在是饿坏了,再不吃点儿东西,他可能就横死街头了,于是,他想到了他的老朋友Tom,
Tom这个糟老头子可是坏得很呀,他给小Jerry出了一个问题,做出来这个问题,小Jerry就能获得糟老头子Tom 
赞助的补给!!!只有伟大的团队可以帮得了Jerry,并将获得荣耀之光,你们能帮可怜的Jerry获得补给吗?
给定一个正整数n,求至少两个正整数使得他们的lcm(最小公倍数)为n,且这些正数的和最小,输出这个最小和。

输入格式

第一行一个整数T1T1e4
接下来T行,每行一个正整数n1n2311

输出格式

输出T行,每行输出”Case #: “(不包括“”),#表示第#组数据,后面跟题目要求的答案,具体输出可参考样例

样例

input
3  12  10  5  
output
Case 1: 7  Case 2: 7  Case 3: 6分解质因子,然后记录每个质因子构成的值,最后累加就好了,但是注意,,如果他的质因子个数只有一个,或者他是质数的话直接输出n+1
#include<iostream>  #include<cstdio>  #include<cmath>  using namespace std;  typedef long long ll;  const int N=1e6+7;  int prime[N]={1,1,0};  ll pre[N];  void f_prime(){      int sum=0;      for(int i=2;i<=N;i++){          if(prime[i]==0){              pre[sum++]=i;               for(int j=i+i;j<=N;j+=i){                  prime[j]=1;              }          }      }  }    int main(){      f_prime();      int t;      int k=0;      cin>>t;      while(t--){          k++;          ll n;          scanf("%d",&n);          ll n1=n;          printf("Case %d: ",k);          if(n==1){              printf("2\n");              continue ;          }          ll m=sqrt(n+1);          ll ans=0;          int x=0;          for(int i=0;pre[i]<=m;i++){              ll sum=1;              if(n%pre[i]==0){                  x++;                  while(n%pre[i]==0){                      sum*=pre[i];                      n/=pre[i];                  }                  ans+=sum;              }          }          if(n>1){              x++;              ans+=n;          }          if(x>1) {              printf("%lld\n",ans);          }          else {              printf("%lld\n",1+n1);          }      }      return 0;  } 

 

  
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!