3971.最小的商
题目意思:
给定n个数字和一个数字k,找到这n个数字中能被k整除的最大值
题目思路:
暴力遍历一遍即可
#include <bits/stdc++.h>
#define FAST std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
typedef long long ll;
int T;
int n,m;
const int maxn = 1e5 + 10;
int main()
{
cin >> T;
while(T--){
cin >> n >> m;
int tmp;
int ans = maxn;
for(int i = 1;i <= n;i++)
{
cin >> tmp;
if(m % tmp == 0) ans = min(ans ,m / tmp);
}
cout << ans <<"\n";
}
return 0;
}
3972 方格集合数量
题目大意:
在一个n * m的棋盘中,每个位置有一个数字可能是0,可能是1
每一行和每一列数值相同的元素可以组成一个集合
求这个集合的数量
解题思路:
根据题目可得,假设一行的数字分别是 1 0 1 0 1,那么1组成的集合应该是 {1}(第一个1),{1}(第三个1),{1}(第5个1),然后组成2个1的集合是3个,组成3个1的集合是1个,因此可以用组合计数的方式去进行计算
注意行列计算的时候,比如Ctmp取1是在行列中都取过,所以最后需要减去一次n * m的数量
#include <bits/stdc++.h>
#define FAST std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
typedef long long ll;
const int maxn = 1e2 + 10;
ll mp[maxn][maxn];
ll ans;
ll a[62];
int n,m;
void pre()
{
a[1] = 1;
for(int i = 2;i <= 50;i++) a[i] = 2 * a[i - 1] + 1;
}
int main()
{
pre();
cin >> n >> m;
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= m;++j) cin >> mp[i][j];
}
// ans += n * m;
for(int i = 1;i <= n;i++)
{
int tmp = 1;
for(int j = 2;j <= m;j++)
{
if(mp[i][j] == mp[i][1]) tmp++;
}
//cout << a[tmp] <<" "<<a[m - tmp]<<"\n";
ans += a[tmp];
ans += a[m - tmp];
//if(tmp > 0) ans -= tmp * 2;
}
for(int j = 1;j <= m;++j)
{
int tmp = 1;
for(int i = 2;i <= n;++i)
{
if(mp[i][j] == mp[1][j]) tmp++;
}
//cout <<"tmp"<<tmp<<"\n";
//cout << a[tmp] <<" "<< a[n - tmp]<<"\n";
ans += a[tmp];
ans += a[n - tmp];
//ans -= tmp * 2;
}
ans -= n * m;
//if(n == 1 && m == 1) ans = 1;
cout << ans <<"\n";
return 0;
}
3973.
题目大意:
给定n个牛和m个空调,空调的位置是b[i],空调的覆盖距离是[b[i] - r,b[i] + r],求最小距离能够让所有牛牛吹到空调
解题思路:
分析题目数据n是1e5,同时最大距离是2e9,那么常规暴力是肯定不能行得通的
既然是求最后的距离,那么这又是一道经典的二分枚举最后数值的题目
时间复杂度大约在1e8左右
同时在二分的时候我们需要注意以下几点
1.如果牛还在目前位置到的左端点的左边,直接退出并且增加空调距离
2.如果牛在目前位置的右端点的右边,那么需要移动目前空调的坐标
3.如果所有牛牛目前都能吹到,更新答案的同时再缩小右端点
因此答案就显而易见的得出来啦
#include <bits/stdc++.h>
#define FAST std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
ll a[maxn];
ll b[maxn];
int m,n;
ll ans;
void search()
{
ll L = 0;
ll R = 2000000000;
while(L <= R)
{
//cout <<"????"<<L<<" "<<R<<"\n";
ll mid = (L + R) >> 1;
int pos = 1;
int pos2 = 1;
while(pos <= n && pos2 <= m)
{
if(a[pos] >= b[pos2] - mid && a[pos] <= b[pos2] + mid)
{
pos++;
}
else if(a[pos] < b[pos2] - mid)
{
// L = mid + 1;
break;
}
else pos2++;
}
if(pos <= n) L = mid + 1;
if(pos > n)
{
ans = min(ans,mid);
R = mid - 1;
}
}
}
int main()
{
FAST
cin >> n >> m;
for(int i = 1;i <= n;++i) cin >> a[i];
for(int i = 1;i <= m;++i) cin >> b[i];
ans = 2000000000;
search();
cout << ans <<"\n";
return 0;
}