P2759 奇怪的函数
题目描述
使得 x^x 达到或超过 n 位数字的最小正整数x 是多少?
输入格式
一个正整数 n。
输出格式
使得 x^x 达到 n 位数字的最小正整数 x。
一道二分题目
首先n^n是一定会大于等于n位的
所以右端点就确定了
所以区间为【1,n】
比较难的就是怎么表示位数,百度发现c++自带log10函数所以可以用x*log10(x)=log10(x*x)来表示位数
完整代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
long long n,x,r,l;
cin>>n;
l=1,r=n+10;
while(l<r)
{
long long mid=(l+r)/2;
long long sum=(mid*log10(1.0*mid))+1;
if(sum<n)
{
l=mid+1;
}
else
{
r=mid;
}
}
cout<<l<<endl;
return 0;
}
P1111 修复公路
题目背景
A 地区在地震过后,连接所有村庄的公路都造成了损坏而无法通车。政府派人修复这些公路。
题目描述
给出 A 地区的村庄数 N,和公路数 M,公路是双向的。并告诉你每条公路的连着哪两个村庄,并告诉你什么时候能修完这条公路。问最早什么时候任意两个村庄能够通车,即最早什么时候任意两条村庄都存在至少一条修复完成的道路(可以由多条公路连成一条道路)。
输入格式
第 11 行两个正整数 N,M。
下面 M 行,每行 33 个正整数 x,y,t,告诉你这条公路连着x,y 两个村庄,在时间t时能修复完成这条公路。
输出格式
如果全部公路修复完毕仍然存在两个村庄无法通车,则输出−1,否则输出最早什么时候任意两个村庄能够通车。
这题考察并查集
要注意路是同时进行修复的
所以我们可以按修路时间来排序,然后把用时短的合并在一起,当所有村庄都被连通时输出目前的最大时间
如果按时间排序的话,对应连通的路线也要跟着变,此时可以用结构体来处理
完整代码
#include<bits/stdc++.h>
using namespace std;
struct road
{
int x;
int y;
int t;
}a[100005];
int fa[100005],n,m;
bool op(road s,road h)
{
return s.t<h.t;
}
void iint()
{
for(int i=1;i<=n;i++)
{
fa[i]=i;
}
}
int find(int u)
{
if(fa[u]==u)
{
return u;
}
else
{
return fa[u]=find(fa[u]);
}
}
void join(int v,int u)
{
u=find(u);
v=find(v);
if(u==v)
{
return;
}
fa[v]=u;
}
bool judge()
{
int sum=0;
for(int i=1;i<=n;i++)
{
if(fa[i]==i)
{
sum++;
}
if(sum==2)
{
return 0;
}
}
return 1;
}
int main()
{
cin>>n>>m;
iint();
for(int i=1;i<=m;i++)
{
cin>>a[i].x>>a[i].y>>a[i].t;
}
sort(a+1,a+m+1,op);
for(int i=1;i<=m;i++)
{
join(a[i].x,a[i].y);
if(judge())
{
cout<<a[i].t;
return 0;
}
}
cout<<-1<<endl;
return 0;
}
P8800 [蓝桥杯 2022 国 B] 卡牌
题目描述
这天,小明在整理他的卡牌。
他一共有 n 种卡牌,第 i 种卡牌上印有正整数数 i(i∈[1,n]), 且第 i 种卡牌现有 ai 张。
而如果有 n 张卡牌,其中每种卡牌各一张,那么这 n 张卡牌可以被称为一套牌。小明为了凑出尽可能多套牌,拿出了 m 张空白牌, 他可以在上面写上数 i,将其当做第 i 种牌来凑出套牌。然而小明觉得手写的牌不太美观,决定第 i 种牌最多手写 bi 张。
请问小明最多能凑出多少套牌?
输入格式
输入共 3 行,第一行为两个正整数 n,m 。
第二行为 n 个正整数 1,2,…,a1,a2,…,an 。
第三行为 n 个正整数 1,2,…,b1,b2,…,bn 。
输出格式
一行,一个整数表示答案。
二分;每次搜索能够凑出来的最大牌数,
这个最大牌套数需要满足每种卡片都足够
所以左区间为初始的ai,右区间为ai+bi;
这个mid数需要满足mid-ai<bi,否则不满足,区间改变
然后所有mid-ai(即需要手写的值加起来)少于等于m张牌
如果mid数满足就要使右边缩小为mid,继续二分,
不满足则使左边增大为mid,继续二分;
完整代码
#include<bits/stdc++.h>
using namespace std;
long long n,m;
long long a[200005],b[200005];
bool check(int x)
{
long long sum=0;
for(int i=1;i<=n;i++)
{
if(x-a[i]>b[i])
{
return false;
}
sum+=max(x-a[i], (long long)0);
}
if(sum<=m)
{
return true;
}
else
{
return false;
}
}
int main()
{
cin>>n>>m;
for(long long i=1;i<=n;i++)
{
cin>>a[i];
}
for(long long i=1;i<=n;i++)
{
cin>>b[i];
}
long long l=1,r=1e9;
while(l+1<r)
{
long long mid=(l+r)/2;
if(check(mid))
{
l=mid;
}
else
{
r=mid;
}
}
if(check(r))
{
cout<<r;
}
else
{
cout<<l;
}
return 0;
}