http://43.139.152.26 枪声问题(桂城真题)
大家好我是清墨,今天我们由一道题来复习我们以前学过的内容。
题目描述
大联欢的最后项目是小明和小李的射击比赛。比赛规则是这样的,每次两人同时射击,每个人有 S 枚子弹进行射击,第 1 秒两人同时打出第一枚子弹,以后的 s-1 子弹可以自己根据一定的间隔时间打出,设小明后面的子弹每隔 t1 秒打出一枚子弹,小李后面的子弹每隔 t2 秒打出一枚子弹,如 t1=2 时,则小明子弹打出的时刻分别为 1,4,7,10,13,…,同理可得小李子弹打出的时刻。如果某一时刻两人同时打出子弹,则只能听到一次响声,你知道这两个人的比赛过程中我们共能听到几次枪声吗?
输入格式
输入数据共有三行. 第一行有一个正整数 S,它的范围[1..100000]。
第二行有一个正整数 t1,它的范围[1..10000]。
第三行有一个正整数 t2,它的范围[1..10000]。
输出格式
比赛过程中能听到几次枪声。
样例
输入数据 1
5
2
3
输出数据 1
8
方法一
看到这道题,我们第一时间想的是下标计数打表,用数组?
NO,用STL映射,因为我们数组的范围不够题目的要求。
代码:
#include<bits/stdc++.h>
using namespace std;
int n,t2,t1,S;
int x;
map<int,int>a;
int main(){cin>>n>>t1>>t2;for(int i=0;i<n;i++){a[1+(t1+1)*i]=1;//1+0*(t1+1) 1+1*(t1+1) 1+2*(t1+1)......1+(n-1)(t1+1)//这就是i从0到n的原因a[1+(t2+1)*i]=1;}cout<<a.size();return 0;
}
方法二
有些同学豁然开朗想到能用集合来写。
代码:
#include<bits/stdc++.h>
using namespace std;
set<int>x;
int t1,t2,ss;
int main()
{cin>>ss>>t1>>t2;for(int i=0;i<=ss-1;i++){x.insert(i*(t1+1));//其实你加不加一都没有关系的x.insert(i*(t2+1));}cout<<x.size();return 0;}
方法三
清墨想到了用公倍数来写。
代码:
#include<bits/stdc++.h>
using namespace std;
//转化成找t1 t2的最小公倍数的倍数个数
//总的枪数2*s-同时的(t1 t2的最小公倍数的倍数个数+第一枪)
//在提前结束那个人的时间段找最小公倍数的个数
int main()
{int s,t1,t2,gcd,lcm,ans;cin>>s>>t1>>t2;t1++; //转化成倍数问题,两枪之间间隔 t1 秒,枪响又是 1 秒,所以,一个周期就是 t1+1 秒 t2++; //两枪之间间隔 t2 秒,枪响又是 1 秒,所以,一个周期就是 t1+1 秒 if(t1>t2) swap(t1,t2); //一般化处理,确保t1<=t2;//t1<t2,小明的枪声先结束,最后的一声枪响在 (s-1)*t1 //小明抢响时间为 1 1+(t1+1) 1+2*(t1+1) ...... 1+(n-1)*(t1+1) //平移坐标轴 枪响时间为 0,t1,2*t1,3*t1,.....,(s-1)*t1//小李的枪响时间为 1 1+(t2+1) 1+2*(t2+1) 1+(n-1)*(t2+1)// 两个人枪声重叠的时间为最小公倍数的倍数时间点gcd=__gcd(t1,t2); //先求最大公约数 lcm=t1*t2/gcd; // 公式法求最小公倍数 ans = 2*s - (s-1)*t1/lcm -1 ; //有多少个公倍数的倍数,就扣减多少 ,最后减 1 是因为还有 0 时间点重叠的那一枪 cout<<ans;return 0;}