天梯选拔赛第一场+第二场
题解:因为数据很小我们可以枚举每一个状态然后判断一下是否可以达到孵化的温度即可
我们用二进制枚举,一共1<<m相当于2的m次方,用二进制枚举每一个状态
//#include <bits/stdc++.h> //#pragma GCC optimize("Ofast") #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> //#define double long double #define int long long #define endl '\n' using namespace std; const int N=1e5,M=1e1; const int INF = 0x3f3f3f3f; const int mod=1e9+7; typedef pair<int,int> PII; int biao[N]; PII c[N]; int k[N]; int p[N]; void solve() { int n,m; cin>>n>>m; int zz=0; for(int i=1;i<=n;i++) { int a,b,mi; cin>>a>>b>>mi; zz=max(zz,b); for(int j=a;j<=b;j++) { biao[j]=mi; } } for(int i=0;i<m;i++) { int l,r,ki,pi; cin>>l>>r>>ki>>pi; c[i]={l,r}; k[i]=ki; p[i]=pi; } int ans=0; int sum=INF; for(int i=0;i<1<<m;i++) { ans=0; int op[N]={0}; for(int j=0;j<m;j++) { if(i&1<<j) //判断这一位是否是开启的状态 { ans+=p[j]; for(int ea=c[j].first;ea<=c[j].second;ea++) { op[ea]+=k[j]; } } } int f=0; for(int j=1;j<=zz;j++) { if(biao[j]==0) continue; else { if(biao[j]>op[j]) { f=1; break; } } } if(!f) { sum=min(sum,ans); } } cout<<sum<<endl; } signed main(){ std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int T=1; // cin>>T; while(T--){ solve(); } return 0; }
下面写另外一个暴力搜索的版本
#include <bits/stdc++.h> //#pragma GCC optimize("Ofast") #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> //#define double long double #define int long long #define endl '\n' using namespace std; const int N=1e6+5,M=1e9+7; const int INF = 0x3f3f3f3f3f3f3f3f; const int mod=998244353; typedef pair<int,int> PII; int n,m; int biao[N]={0}; struct G { int l,r; int k,p; }a[N]; int ans=INF; void dfs(int dep,bool op,int p) { if(dep>m) return; if(op) { p+=a[dep].p; int cnt=0; for(int i=1;i<=100;i++) { if(i>=a[dep].l && i<=a[dep].r) biao[i]-=a[dep].k; if(biao[i]<=0) cnt++; } if(cnt==100) { ans=min(ans,p); return; } dfs(dep+1,1,p); for(int i=a[dep+1].l;i<=a[dep+1].r;i++) { biao[i]+=a[dep+1].k; } dfs(dep+1,0,p); } else { dfs(dep+1,1,p); for(int i=a[dep+1].l;i<=a[dep+1].r;i++) { biao[i]+=a[dep+1].k; } dfs(dep+1,0,p); } } void solve() { cin>>n>>m; for(int i=1;i<=n;i++) { int l,r,val; cin>>l>>r>>val; for(int j=l;j<=r;j++) { biao[j]=val; } } for(int i=1;i<=m;i++) { int l,r,k,p; cin>>l>>r>>k>>p; a[i]={l,r,k,p}; } dfs(1,1,0); for(int i=a[1].l;i<=a[1].r;i++) biao[i]+=a[1].k; dfs(1,0,0); cout<<ans<<endl; } signed main(){ std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int T=1; // cin>>T; while(T--){ solve(); } return 0; }
题解:直接暴力枚举每一个矩形即可,枚举左上角和右下角的点即可,4个for就可以了,然后用set套vector筛
#include <bits/stdc++.h> //#pragma GCC optimize("Ofast") #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> //#define double long double #define int long long #define endl '\n' using namespace std; const int N=1e6+5,M=1e9+7; const int INF = 0x3f3f3f3f3f3f3f3f; const int mod=998244353; typedef pair<int,int> PII; PII a[N]; void solve() { int n; cin>>n; for(int i=1;i<=n;i++) { int x,y; cin>>x>>y; a[i]={x,y}; } set<vector<int>> b; for(int x1=0;x1<=50;x1++) { for(int y1=0;y1<=50;y1++) { for(int x2=0;x2<=50;x2++) { for(int y2=0;y2<=50;y2++) { vector<int> s; for(int i=1;i<=n;i++) { if(a[i].first>=x1 && a[i].first<=x2 && a[i].second>=y1 && a[i].second<=y2) { s.push_back(i); } } b.insert(s); } } } } cout<<b.size()<<endl; } signed main(){ std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int T=1; // cin>>T; while(T--){ solve(); } return 0; }
http://162.14.124.219/training/1/problem/C-01-K
题解:这道题就是跑一个搜索,本题只需要去找3个人就行,所以我们可以直接枚举抓人的先后顺序,然后就一直跑最短路即可,用广搜就行,写两个BFS不改个判断条件即可,一个有障碍物一个没有
问题:最后才看这道题当时看的急,我以为有n个人,那就不是直接枚举顺序的事情了,慢了一步
#include <bits/stdc++.h> //#pragma GCC optimize("Ofast") #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> //#define double long double #define int long long #define endl '\n' using namespace std; const int N=200+5,M=1e9+7; const int INF = 0x3f3f3f3f3f3f3f3f; const int mod=998244353; typedef pair<int,int> PII; int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; char a[N][N]; PII b[N]; int vis[N][N]; int dis[N][N]; int s[N]; int n,m; int sx,sy; int ex,ey; int ans=INF; int ss; int bfs1(int x1,int y1,int x2,int y2) { for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { dis[i][j]=vis[i][j]=0; } } queue<PII> q; q.push({x1,y1}); while (!q.empty()) { auto t=q.front(); q.pop(); vis[t.first][t.second]=1; for(int i=0;i<4;i++) { int xx=t.first+dx[i]; int yy=t.second+dy[i]; if(!vis[xx][yy]) { if(xx>=1 && xx<=n && yy>=1 && yy<=m) { dis[xx][yy]=dis[t.first][t.second]+ss+1; vis[xx][yy]=1; if(xx==x2 && yy==y2) { return dis[xx][yy]; } q.push({xx,yy}); } } } } } int bfs2(int x1,int y1,int x2,int y2) { for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { dis[i][j]=vis[i][j]=0; } } queue<PII> q; q.push({x1,y1}); while (!q.empty()) { auto t=q.front(); q.pop(); vis[t.first][t.second]=1; for(int i=0;i<4;i++) { int xx=t.first+dx[i]; int yy=t.second+dy[i]; if(!vis[xx][yy]) { if(xx>=1 && xx<=n && yy>=1 && yy<=m && a[xx][yy]!='#') { dis[xx][yy]=dis[t.first][t.second]+ss+1; vis[xx][yy]=1; if(xx==x2 && yy==y2) { return dis[xx][yy]; } q.push({xx,yy}); } } } } } void dfs(int i,int j,int z) { int x=0; ss=0; x+=bfs1(sx,sy, b[i].first,b[i].second); ss+=s[i]; x+=bfs1(b[i].first,b[i].second,b[j].first,b[j].second); ss+=s[j]; x+=bfs1(b[j].first,b[j].second,b[z].first,b[z].second); ss+=s[z]; x+=bfs2(b[z].first,b[z].second,ex,ey); ans=min(ans,x); } void solve() { cin>>n>>m; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { cin>>a[i][j]; } } cin>>sx>>sy; for(int i=1;i<=3;i++) { int x,y; cin>>x>>y; b[i]={x,y}; } cin>>ex>>ey; for(int i=1;i<=3;i++) { cin>>s[i]; } for(int i=1;i<=3;i++) { for(int j=1;j<=3;j++) { for(int z=1;z<=3;z++) { if(i!=j && i!=z && z!=j) { dfs(i,j,z); } } } } cout<<ans<<endl; } signed main(){ std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int T=1; // cin>>T; while(T--){ solve(); } return 0; }
I 找除数
题解:这是一道数学题,我们想要知道n有多少个除数那么我们需要分解素数
推出公式
n=p1x∗p2y∗p3z……,p是素数,n的除数的数量就=(x+1)(y+1)(z+1)……
所以我们用一个欧拉筛加一个质因分解就行了
#include <bits/stdc++.h> //#pragma GCC optimize("Ofast") #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> //#define double long double #define int long long #define endl '\n' using namespace std; const int N=1e6+5,M=1e9+7; const int INF = 0x3f3f3f3f3f3f3f3f; const int mod=998244353; typedef pair<int,int> PII; int prime[1000006],cnt; bool st[1000006]; void get_prime(int n){ for(int i=2;i<=n;i++){ if(!st[i]){ prime[cnt++]=i; } for(int j=0;i*prime[j]<=n;j++){ st[i*prime[j]]=1; if(i%prime[j]==0) break; } } } void solve() { int x; cin>>x; vector<int> g; for(int i=0;prime[i]<=(x / prime[i]) && i<cnt;i++) { int dp=0; while(x%prime[i]==0) { dp++; x/=prime[i]; } if(dp) { g.push_back(dp); } } if(x>1) { g.push_back(1); } int ans=1; for(auto p:g) { ans=ans*(p+1); } cout<<ans<<endl; } signed main(){ std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int T=1; cin>>T; get_prime(100000); while(T--){ solve(); } return 0; }
题解:单纯一个大模拟,只要熟悉STL的使用即可通过,具体看代码实现
原因:时间不够,题目太长,速度太慢
#include <bits/stdc++.h> //#pragma GCC optimize("Ofast") #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> //#define double long double #define int long long #define endl '\n' using namespace std; const int N=1e5,M=1e1; const int INF = 0x3f3f3f3f; const int mod=1e9+7; typedef pair<string,int> PII; void solve() { int n,k; cin>>n>>k; queue<int> q; queue<int> pao; stack<int> op; for(int i=1;i<=n;i++) { int x; cin>>x; op.push(x); } while (op.size()) { q.push(op.top()); op.pop(); } stack<int> jin; stack<int> he; while (1) { if(q.size()==0 && he.size()==0) { if(jin.size()>=2) { while (jin.size()) { cout<<jin.top()<<" "; jin.pop(); } cout<<endl; } else { pao.push(jin.top()); jin.pop(); } break; } if(q.size()==0 && he.size()!=0) { if(jin.size()>=2) { while (jin.size()) { cout<<jin.top()<<" "; jin.pop(); } cout<<endl; } else { pao.push(jin.top()); jin.pop(); } while (he.size()) { q.push(he.top()); he.pop(); } } if(q.size()!=0) { int x; x = q.front(); q.pop(); if (jin.size() == 0) { jin.push(x); } else { int y = jin.top(); if (x > y && x - y <= k) { jin.push(x); } else { if (he.size() == 0) { he.push(x); } else { int heyi = he.top(); if (heyi > y && heyi - y <= k) { jin.push(heyi); he.pop(); } he.push(x); } } } } } while (pao.size()) { cout<<pao.front()<<" "; pao.pop(); } } signed main(){ std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int T=1; // cin>>T; while(T--){ solve(); } return 0; }
原因:这道题难度一般,是一个图题,一看就很明显,可惜的是当时没有时间读这道题,赛后补题一次过
题解:我们可以看到每个精灵融合都有各自的顺序
谁和谁可以到谁那种,所以我们可以把它看成图,跑一边深搜,从你要搜的精灵开始往下搜到叶子节点即可
然后还要记得处理一下升级的问题,就是找规律,很简单
#include <bits/stdc++.h> //#pragma GCC optimize("Ofast") #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> //#define double long double #define int long long #define endl '\n' using namespace std; const int N=1e5+10,M=1e1; const int INF = 0x3f3f3f3f; const int mod=1e9+7; typedef pair<string,int> PII; int ans=0; vector<int> tu[N]; int ji[N]; int sheng[N]; int vis[N]; int yi[4][N]; void dfs(int u) { vis[u]=1; for(int i=0;i<tu[u].size();i++) { int t=tu[u][i]; if(!vis[t]) { ans+=yi[ji[t]][sheng[t]]; vis[t]=1; dfs(t); } } return; } void solve() { int x,m; cin>>x>>m; yi[1][2]=1; yi[2][2]=1; yi[3][2]=1; for(int i=1;i<=3;i++) { int k=1; int k1=2; int k2=5; for(int j=3;j<=100;j++) { if(i==1) { yi[i][j]=yi[i][j-1]+k; k++; } if(i==2) { yi[i][j]=yi[i][j-1]+k1; k1+=2; } if(i==3) { yi[i][j]=yi[i][j-1]+k2; k2+=5; } } } for(int i=1;i<=m;i++) { int a,b,c,d; cin>>a>>b>>c>>d; tu[a].push_back(b); ji[b]=c; sheng[b]=d; } dfs(x); cout<<ans<<endl; } signed main(){ std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int T=1; // cin>>T; while(T--){ solve(); } return 0; }
题解:这道题直接把每一个红石连起来,看成一条线性的
然后我们可以计算每一个热源可以辐射的范围即可
公式推出为 (15-m)*2+1=d 就是辐射范围我们把这条线长度除d就可以了
#include <bits/stdc++.h> //#pragma GCC optimize("Ofast") #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> //#define double long double #define int long long #define endl '\n' using namespace std; const int N=1e5+10,M=1e1; const int INF = 0x3f3f3f3f; const int mod=1e9+7; typedef pair<string,int> PII; int x[N]; int y[N]; void solve() { int n,m; cin>>n>>m; int ans=1; for(int i=1;i<=n;i++) { cin>>x[i]>>y[i]; if(i!=1) { ans+=abs(x[i-1]-x[i])+abs(y[i-1]-y[i]); } } if(m==0) { cout << 0 << endl; } else { int d=(15-m)*2+1; int sum=ans/d+(ans%d?1:0); cout<<sum<<endl; } } signed main(){ std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int T=1; // cin>>T; while(T--){ solve(); } return 0; }
题解:首先我们先存一下每一个数的值,然后就是这个值在存一下奇偶性len[][]
我们可以先枚举si然后在枚举中间点,然后算出左右两边的值lsum rsum
然后对于这个si我们找一个sj lsum=rsum+sj 所以我们可以看出sj的值就是lsum-rsum可知
然后在len里面找一下即可,注意奇偶性
#include <bits/stdc++.h> //#pragma GCC optimize("Ofast") #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> //#define double long double #define int long long #define endl '\n' using namespace std; const int N=2e5+10,M=1e1; const int INF = 0x3f3f3f3f; const int mod=1e9+7; typedef pair<string,int> PII; string s[N]; int num[N]; int len[100][2]; int get_num(string ss) { int ans=0; int cnt=ss.size(); int k=0; while (cnt--) { ans+=(ss[k]-'0'); k++; } return ans; } void solve() { int n; cin>>n; for(int i=1;i<=n;i++) { cin>>s[i]; num[i]=get_num(s[i]); len[num[i]][s[i].size()&1]++; } int ans=0; for(int i=1;i<=n;i++) { int lsum=0; for(int j=0;j<s[i].size();j++) { int st=s[i][j]-'0'; lsum+=st; int rsum=num[i]-lsum; if(rsum>lsum) continue; ans+=len[lsum-rsum][s[i].size()&1]; } } for(int i=1;i<=n;i++) { int rsum=0; for(int j=s[i].size()-1;j>0;j--) { int st=s[i][j]-'0'; rsum+=st; int lsum=num[i]-rsum; if(lsum>rsum) continue; ans+=len[rsum-lsum][s[i].size()&1]; } } cout<<ans<<endl; } signed main(){ std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int T=1; // cin>>T; while(T--){ solve(); } return 0; }