D. Tom的战力问题
Tom被斯派克揍了TAT。
Tom下定决心要战胜斯派克。
但是在战胜最强的斯派克之前,Tom要先打败其他的狗。为此,他打算先收集一下信息。
现在Tom在了得到了一些关于战斗力的小道消息,例如X号狗狗的战力比Y号狗狗的战力高S点。
Tom想知道利用这些消息,能不能判断出某两只狗之间的战力高低?高多少?
输入格式
第一行包含三个整数N,M和Q。N表示狗总数,M表示Tom知道消息的总数,Q表示小Tom想询问的数量。
以下M行每行三个整数,X,Y和S。表示X号狗的战力比Y号狗的战力高S点。
以下Q行每行两个整数,X和Y。表示Tom想知道X号狗的战力比Y号狗的战力高几点。
2≤N≤1000
1≤M,Q≤N
1≤X,Y≤N
−1000≤S≤1000
数据保证没有矛盾。
输出格式
对于每个询问,如果不能判断出X比Y高几点输出−1。否则输出X比Y高多少战力点。
样例
10 5 3 1 2 10 2 3 10 4 5 -10 5 6 -10 2 5 10 1 10 1 5 3 5
-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)); }
现在,他想让你根据这个函数来解决问题
输入格式
单组输入,每组一行,有两个整数m和n(0≤m≤3,0≤n≤27)
输出格式
请输出上面代码的运行结果
样例
1 1
3
0 1
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人之多(1≤n≤106),她们每个人的学号都是1018 内的一个正整数。
Jerry 早早地就掌握了她们每个人的学号,并且知道她们之中有一个人和Tom约会去了!
Jerry 统计了在场所有妹子的学号,他想知道,哪个人没来?
输入格式
第一行是一个整数n,代表一共有n只妹纸
以下n行每行一个整数,代表每只妹纸的学号
接下来一个空行
以下n−1行每行一个整数,代表每只来了的妹纸的学号
输出格式
输出没来的妹纸的学号。
样例
3 10061061 10061023 10061201 10061023 10061201
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阶楼梯被破坏了。
(1≤T,m≤10,1≤n≤1000,1≤ai≤n)。
输出格式
对于每组输入,输出方案数对109+7取模的结果。
样例
3 1 1 1 8 1 1 10 2 1 2
0 13 0
#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,求解下列方程:
Tom顿时傻眼了,现在只有你能来帮他挽回颜面了,快来帮帮它吧。

输入格式
第一行输入一个T代表有T组输入。
每组输入包含两个正整数a,b。
(1≤T≤100,1≤a,b≤10000)
输出格式
对于每组输入,每行输出一组x,y,如果有多组,则输出x最小的,x,y中间用空格隔开。如果无解输出−1。
样例
3 100 50 3 3 6 7
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之和。
样例
4 1 2 1 3 2 4
8
#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,且这些正数的和最小,输出这个最小和。
输入格式
第一行一个整数T(1≤T≤1e4)
接下来T行,每行一个正整数n(1≤n≤231−1)
输出格式
输出T行,每行输出”Case #: “(不包括“”),#表示第#组数据,后面跟题目要求的答案,具体输出可参考样例
样例
3 12 10 5
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; }