- 伍衍 的博客
DAY3 题解
- @ 2025-7-17 18:29:45
这次只有 /(ㄒoㄒ)/~~(本来应该有 的 QAQ)
解:按甜度和咸度分别降序排序,在计算最多吃几个,取最小值。
代码:
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+50;
long long a[N],b[N];
bool cmp(long long a,long long b){
return a>b;
}
int main(){
freopen("eat.in","r",stdin);
freopen("eat.out","w",stdout);
long long n,x,y;
cin >> n >> x >> y;
for(long long i=1;i<=n;i++){
cin >> a[i];
}for(long long i=1;i<=n;i++){
cin >> b[i];
}
sort(a+1,a+n+1,cmp);
sort(b+1,b+n+1,cmp);
long long as=0,bs=0,am=0,bm=0,flag=1;
for(long long i=1;i<=n;i++){
as+=a[i];
if(as>x){am=i;flag=0;break;}
}
if(flag) am=n;
flag=1;
for(long long i=1;i<=n;i++){
bs+=b[i];
if(bs>y){bm=i;flag=0;break;}
}
if(flag) bm=n;
cout << min(am,bm);
}
解:代码为打表后找规律版本,实际只需三重循环枚举即可(范围~),代码应该很好理解,jh 函数表示在后面添加一个 1 , 即获取下一个纯 1 数。
代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
int jh(int x){
return x*10+1;
}
signed main(){
freopen("three.in","r",stdin);
freopen("three.out","w",stdout);
int n;
cin >> n;
int a=1,b=1,c=1;
if(n==1){
cout << 3 << endl;
return 0;
}
for(int i=2;i<=n;i++){
if(a==b&&b==c){
c=jh(c);
a=1;
b=1;
}else if(a==b&&b!=c){
b=jh(b);
a=1;
}else if(a!=b){
a=jh(a);
}
}
cout << a+b+c << endl;
}
暴力骗了
解:简单递推 DP
a[i][j] 表示首位是 i,末位是 j 的数字个数。
先枚举 (首位j末尾i),每次将答案加上 a[i][j]*2( 在前面和后面算两组解),同时将 a[j][i] 增加 。
特判:由于存在个位数解,所以当 i=j 时额外增加一组解
代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
int a[11][11];
signed main(){
freopen("number.in","r",stdin);
freopen("number.out","w",stdout);
int n;
cin >> n;
int ans=0;
for(int i=1;i<=n;i++){
int x=i%10,y=i;
while(y/10>0) y/=10;
if(x==y) ans++;
ans+=a[x][y]*2;
a[y][x]++;
}
cout << ans;
}
解:首先,如果一个数有可能成为中位数,则比他小的数也可能成为。所以这题具有二段性,可以用二分(bs1),check函数比较难写,但其实也不难,我们可以用一个标记数组,把大于mid的标记为1,小的标记为0,在求一个二位前缀和,每次枚举所有矩阵,如果里面的1数量大于 ,则返回1,否则返回0,二分结果即为答案
代码:现在不能写了
把 -1e18 写成了 -1 ,当时考试时间只剩几分钟了,我又手滑把自测点成了提交,导致本来能 的代码直接爆 了(QAQ QAQ QAQ QAQ QAQ QAQ QAQ QAQ QAQ QAQ)
思路:模板题。
代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
typedef pair<int,int> PII;
signed main(){
freopen("merge.in","r",stdin);
freopen("merge.out","w",stdout);
int n;
cin >> n;
vector<PII> a;
for(int i=0;i<n;i++){
int x,y;
cin >> x >> y;
a.push_back({x,y});
}
vector<PII> ans;
sort(a.begin(),a.end());
int l=-1e18,r=-1e18;
for(auto it:a){
if(r<it.first){
if(l!=-1e18) cout << l << " " << r << endl;
l=it.first,r=it.second;
}
else r=max(r,it.second);
}
if(l!=-1) cout << l << " " << r << endl;
return 0;
}
解:先用并查集存储每个图,记得存储边数和点数,然后用无序集合存储每个图的根顶点。最后判断每个连通块是否有环(即边数=点数),如果都满足,则结果为 ( 为连通块的数量)
代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+50,mod=998244353;
int fa[N],s1[N],s2[N];
void init(int n){
for(int i=1;i<=n;i++){
fa[i]=i;
s1[i]=1;
s2[i]=0;
}
}
int find(int x){
if(x==fa[x]) return x;
else return fa[x]=find(fa[x]);
}
void merge(int a,int b){
int x=find(a),y=find(b);
if(x!=y){
if(s1[x]<s1[y]) swap(x,y);
fa[y]=x;
s1[x]+=s1[y];
s2[x]+=s2[y];
}
}
int qmi(int a,int b){
int res=1;
while(b){
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res%mod;
}
signed main(){
freopen("one.in","r",stdin);
freopen("one.out","w",stdout);
int n,m;
cin >> n >> m;
init(n);
for(int i=1;i<=m;i++){
int a,b;
cin >> a >> b;
s2[find(b)]++;
merge(a,b);
}
unordered_set<int> rts;
for(int i=1;i<=n;i++){
rts.insert(find(i));
}
int cnt=0;
for(auto rt:rts){
if(s1[rt]==s2[rt]) cnt++;
else{
cout << 0;
return 0;
}
}
cout << qmi(2,cnt)%mod << endl;
}