一,训练赛补题:1,Searching for Soulmates;2,Walking Home;二,cf round 789 div2补题:1, Tokitsukaze and Strange Inequality;三,acwing 提高课:acwing 188.武士风度的牛;acwing 173. 矩阵距离;
一,训练赛补题:
1,Searching for Soulmates
题意:给出两个数a,b,有如下操作:a*2,a/2,或者a+1,来使a==b,问最小的操作数;
思路:首先乘和除一定不会交替出现,因为会相互抵消掉的;所以一定有个分界点;
很容易想到分界点前后是先除后乘。
之后 如何运用乘和加来操作呢;
如下情况:
用f(x,y)表示使x和y相等的最小次数;
①:a>b 无解;
②:a*2>b,此时只能加法,return b-a;
③:b是奇数,return f(a,b-1)+1,解释:使a变成b-1,在加1次加法操作;(这个思想太6了);
④:b是偶数且a<=b/2,return f(a,b/2)+1,解释:使a变成b/2,所以前提是a<=b/2,然后进行一次乘法操作;
其实分界点在a<=b后是随机的,所以只要a<=b,对于每次的a,都设置一个分界点,去操作;
#include//#pragma GCC optimize(2) #define rep1(i,a,n) for(ll i=a;i a;i--) #define per2(i,n,a) for(ll i=n;i>=a;i--) #define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false) #define memset(a,i,b) memset((a),(i),sizeof (b)) #define memcpy(a,i,b) memcpy((a),(i),sizeof (b)) #define pb push_back #define endl "n" #define lowbit(m) (-m&m) #define yes cout<<"YESn" #define no cout<<"NOn" #define yi first #define er second using namespace std; typedef long long ll; typedef pair PII; typedef double db; ll a,b; ll f(ll a,ll b) { if(a>b)return 1e18; if(a*2>b)return b-a; if(b%2)return f(a,b-1)+1; if(b%2==0&&a<=b/2)return f(a,b/2)+1; } void solve() { cin>>a>>b; ll c1=0; if(a==b)cout<<0< 1) { if(a<=b) { ll c2=f(a,b); k=min(k,c1+c2); } if(a%2)a++; else a/=2; c1++; } cout< >T; while(T--)solve(); return 0; }
2,walking home
题意:
给你一个n*n的矩阵,由'.'和'H'组成,带'H'的方格不可以走,牛在(1,1)只能向下和向右走,
且转向次数不超过k次,问到达(n,n)有几种方案;
思路:dfs+剪枝优化;
#include//#pragma GCC optimize(2) #define rep1(i,a,n) for(ll i=a;i a;i--) #define per2(i,n,a) for(ll i=n;i>=a;i--) #define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false) #define memset(a,i,b) memset((a),(i),sizeof (b)) #define memcpy(a,i,b) memcpy((a),(i),sizeof (b)) #define pb push_back #define endl "n" #define lowbit(m) (-m&m) #define yes cout<<"YESn" #define no cout<<"NOn" #define yi first #define er second using namespace std; typedef long long ll; typedef pair PII; typedef double db; const int N=1e2+10; char a[N][N]; int st[N][N][5][5]; int n,k; int dfs(int x,int y,int cs,int dir) { if(cs>k)return 0; if(cs==k&&x!=n&&y!=n)return 0; if(x>n||y>n)return 0; if(x==n&&y==n) return 1; int sum=0; if(a[x][y]=='H')return 0; if(dir) { sum+=dfs(x+1,y,cs,1); sum+=dfs(x,y+1,cs+1,0); } else { sum+=dfs(x+1,y,cs+1,1); sum+=dfs(x,y+1,cs,0); } return sum; } void solve() { cin>>n>>k; rep2(i,1,n) rep2(j,1,n)cin>>a[i][j]; cout< >T; while(T--)solve(); return 0; }
二,cf 补题:
1,Tokitsukaze and Strange Inequality
题意:
给你一个长度为n的数组p,问有多少个本质不同的四元组(a,b,c,d)满足p_d" src="https://latex.codecogs.com/gif.latex?1%5Cleq%20a%3Cb%3Cc%3Cd%20%5Cleq%20n%20%5C%20and%20%5C%20p_a%3Cp_c%5C%20and%20%5C%20p_b%3Ep_d" />?
思路:枚举;
枚举的出发点很关键,从pc出发,每次统计出前边比pc小的pa的个数,在统计出满足pb>pd的个数;
可以用树状数组来优化求pa小于pc的个数;
固定pbpc,移动pd,更新pb>pd的个数,枚举得到的答案,所以不从不漏;
#include#pragma GCC optimize(2) #define rep1(i,a,n) for(ll i=a;i a;i--) #define per2(i,n,a) for(ll i=n;i>=a;i--) #define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false) #define memset(a,i,b) memset((a),(i),sizeof (b)) #define memcpy(a,i,b) memcpy((a),(i),sizeof (b)) #define pb push_back #define endl "n" #define lowbit(m) (-m&m) #define yes cout<<"YESn" #define no cout<<"NOn" #define yi first #define er second using namespace std; typedef long long ll; typedef pair PII; typedef double db; const int N=1e4+10; int c[N]; int n,a[N]; void add(int i,int d) { for(;i<=n;i+=lowbit(i))c[i]+=d; } int sum(int i) { int s=0; for(;i>=1;i-=lowbit(i))s+=c[i]; return s; } void solve() { cin>>n; memset(c,0,c); rep2(i,1,n)cin>>a[i]; ll ans=0; rep2(i,3,n) { add(a[i-2],1); ll num=sum(a[i]); rep2(j,i+1,n) { if(a[i-1]>a[j])ans+=num; num+=sum(a[j]); } } cout<>T; while(T--)solve(); return 0; }
三,
1,武士风度的牛;
题意:
思路:标准的bfs搜索,注意细节,判断下一步的地方不一定是a[i][j]=='.'才可以走,这样会把终点
'H'扔掉不走的!!,所以是a[i][j]!='*'才可以!;
if(x>0&&x<=n&&y>0&&y<=m&&a[x][y]!='*'&&st[x][y]==0)
#include#pragma GCC optimize(2) #define rep1(i,a,n) for(ll i=a;i a;i--) #define per2(i,n,a) for(ll i=n;i>=a;i--) #define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false) #define memset(a,i,b) memset((a),(i),sizeof (b)) #define memcpy(a,i,b) memcpy((a),(i),sizeof (b)) #define pb push_back #define endl "n" #define lowbit(m) (-m&m) #define yes cout<<"YESn" #define no cout<<"NOn" #define yi first #define er second using namespace std; typedef long long ll; typedef pair PII; typedef double db; const int N=1e4+10; int n,m; char a[500][500]; int st[500][500]; int dist[500][500]; PII d[]={{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1}}; int sx,sy,edx,edy; int bfs() { queue q; q.push({sx,sy}); st[sx][sy]=1; dist[sx][sy]=0; while(q.size()) { auto t=q.front();q.pop(); rep1(i,0,8) { int x=t.yi+d[i].yi,y=t.er+d[i].er; if(x>0&&x<=n&&y>0&&y<=m&&a[x][y]!='*'&&st[x][y]==0) { st[x][y]=1; q.push({x,y}); dist[x][y]=dist[t.yi][t.er]+1; if(x==edx&&y==edy)return dist[x][y]; } } } return dist[edx][edy]; } signed main() { quick_cin(); cin>>m>>n; rep2(i,1,n) rep2(j,1,m) { cin>>a[i][j]; if(a[i][j]=='K')sx=i,sy=j; if(a[i][j]=='H')edx=i,edy=j; } cout< 2,矩阵距离;
题意:
多源bfs;
其实就是起点变成了所以1的位置;然后把这些1都预先放进队列里;这样再去求各个位置的距离,由于bfs求到的一定是最短距离,所以某个位置的0被更新到的话,一定是距离它最近的1来更新的;
#include#pragma GCC optimize(2) #define rep1(i,a,n) for(ll i=a;i a;i--) #define per2(i,n,a) for(ll i=n;i>=a;i--) #define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false) #define memset(a,i,b) memset((a),(i),sizeof (b)) #define memcpy(a,i,b) memcpy((a),(i),sizeof (b)) #define pb push_back #define endl "n" #define lowbit(m) (-m&m) #define yes cout<<"YESn" #define no cout<<"NOn" #define yi first #define er second using namespace std; typedef long long ll; typedef pair PII; typedef double db; const int N=1e6+10; PII q[N]; int n,m; int dx[]={-1,0,1,0},dy[]={0,1,0,-1}; string s[1010]; int dist[1010][1010]; void bfs() { memset(dist,-1,dist); int hh=0,tt=-1; rep1(i,0,n) rep1(j,0,m) { if(s[i][j]=='1') { q[++tt] = {i,j}; dist[i][j]=0; } } while(hh<=tt) { auto t=q[hh++]; rep1(i,0,4) { int x=t.yi+dx[i],y=t.er+dy[i]; if(x<0||x>=n||y<0||y>=m)continue; if(dist[x][y]!=-1)continue; dist[x][y]=dist[t.yi][t.er]+1; q[++tt] = {x,y}; } } } signed main() { quick_cin(); cin>>n>>m; rep1(i,0,n)cin>>s[i]; bfs(); rep1(i,0,n) { rep1(j,0,m)cout<



