Content
- CF1491D Zookeeper and The Infinite Zoo
- CF1409F Subsequences of Length Two
- CF1477C Nezzar and Nice Beatmap
CF1491D Zookeeper and The Infinite Zoo
题面化简:
给出
q
q
q个询问,问有向图上
u
u
u是否可以到达
v
v
v,图上的边
u
→
(
u
+
v
)
u→(u+v)
u→(u+v)存在的条件是
u
&
v
=
v
u&v=v
u&v=v。
Hint & Sol
- 分析 & & & 是位运算符号,所以数字按二进制表示;
- 快乐找规律!
- 发现加一个非 2 2 2 的幂次等价于加若干个从大到小的 2 2 2 的幂次,因此我们只需要考虑加的数是 2 2 2 的幂的情况;
- 用此方法将一串 11....10 11....10 11....10调为 00...01 00...01 00...01;
- 注意 01 01 01到 10 10 10的转换发现:可以移动一个位 ( 01 → 10 ) (01→10) (01→10),也可以合并多个位 ( 0111 → 1000 ) (0111→1000) (0111→1000);
- 规律找到了,现在看一下可不可行 于是我们发现:
如果 u > v u>v u>v, u u u无法到达 v v v;
如果 u = v u=v u=v, u u u可以到达 v v v;
如果 u < v u<v u<v,一定可以通过符合条件的加法让低位上的 1 1 1变到高位上的 1 1 1,并且二进制中 1 1 1的数量只能变少不能变多。
得出结论(即做法):先判断 u u u是否小于等于 v v v,然后贪心匹配 u u u和 v v v的 1 1 1位置看 v v v的每个 1 1 1是否都能对应到 u u u的不低于这个位置的 1 1 1。
Code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--){
int x,y;
cin>>x>>y;
int z=0;
bool ok=(x<=y);
for(int i=0;i<30;i++){
if((x>>i)&1)
z++;
if((y>>i)&1)
z--;
if(z<0)
ok=false;
}
if(ok)
cout << "YES\n";
else
cout << "NO\n";
}
return 0;
}
CF1409F Subsequences of Length Two
题面化简:
给定两个字符串,给定m次修改机会,求第二个串作为第一个串子序列的最大数量。其中第二个串是长度为2的字符串。
Sol
时间复杂度为
O
(
n
3
)
O(n^3)
O(n3)
三维DP
Code
//CF 1409 F
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,cnt=0;
ll dp[210][210][210];
int main() {
ios::sync_with_stdio(false);
ll t,i,j;
ll m,x,y,k;
cin>>n>>m;
char s1[220],s2[5];
cin>>s1+1>>s2+1;
if(s2[1]==s2[2]){
cnt=0;
for(i=1;i<=n;i++) if(s1[i]==s2[1]) cnt++;
cnt+=m;
if(cnt>n) cnt=n;
cout<<cnt*(cnt-1)/2<<endl;
return 0;
}
memset(dp,-0x3f,sizeof(dp));
for(i=0;i<=m;i++) dp[0][i][0]=0;//初始化
for(i=1;i<=n;i++){
for(j=0;j<=m;j++){
for(k=0;k<=i;k++){
dp[i][j][k]=dp[i-1][j][k];
if(s1[i]==s2[1]) dp[i][j][k]=max(dp[i][j][k],dp[i-1][j][k-1]);
else if(j) dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-1][k-1]);
if(s1[i]==s2[2]) dp[i][j][k]=max(dp[i][j][k],dp[i-1][j][k]+k);
else if(j) dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-1][k]+k);
}
}
}
ll ans=0;
for(i=0;i<=n;i++)
ans=max(ans,dp[n][m][i]);
cout<<ans<<endl;
return 0;
}
CF1477C Nezzar and Nice Beatmap
题面化简:
平面上有
n
n
n个点
(
3
≤
n
≤
5000
)
(
3
≤
n
≤
5000
)
(3\leq n\leq 5000)(3≤n≤5000)
(3≤n≤5000)(3≤n≤5000),问题是要你给出一个点的排列,使得任意连续三个点所形成的角为锐角,若无解则输出
−
1
-1
−1。
Hint
考虑一个钝角三角形的特征:
有且仅有一个钝角且钝角对着最长的边
Sol
选择一个起始点,对于每个选定的点,找还未被选中的点中离它最远的点。
Code
/*
Problem :
Algorithm :
Status :
*/
#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#define DEBUG cerr << "Passing Line " << __LINE__<< " in Function [" << __FUNCTION__ << "].\n";
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
template<class T> inline bool checkMax(T &a,const T &b) {return a < b ? a = b,1 : 0;}
template<typename T, typename...Args> inline void checkMax(T &a,const Args...arg) {checkMax(a,max(arg...));}
template<class T> inline bool checkMin(T &a,const T &b) {return a > b ? a = b,1 : 0;}
template<typename T, typename...Args> inline void checkMin(T &a,const Args...arg) {checkMin(a,min(arg...));}
const int INF = 0x3f3f3f3f;
const ll llINF = 1e18;
const int MAXN = 5005;
int n;
int x[MAXN],y[MAXN],vis[MAXN];
ll dis(int x1,int y1,int x2,int y2){
return (ll)(x1 - x2) * (x1 - x2) + (ll)(y1 - y2) * (y1 - y2);
}
int main(){
// freopen("data.in","r",stdin);
// freopen("data.out","w",stdout);
scanf("%d",&n);
for(int i = 1;i <= n;i++)
scanf("%d%d",&x[i],&y[i]);
printf("1 ");
vis[1] = 1;
for(int i = 2, lst = 1;i <= n;i++){
ll maxx = 0;
int p = lst;
for(int j = 1;j <= n;j++){
if(!vis[j] && dis(x[lst],y[lst],x[j],y[j]) > maxx){
maxx = dis(x[lst],y[lst],x[j],y[j]);
p = j;
}
}
printf("%d ",p);
vis[p] = 1;
lst = p;
}
return 0;
}
//CF 1477 C 2
#include"bits/stdc++.h"
using namespace std;
#define ri register int
#define ll long long
#define N 5010
int n,ans[N],ok[N];
ll x[N],y[N];
int main(){
ios::sync_with_stdio(false);
cin>>n;
for(ri i=1;i<=n;++i) cin>>x[i]>>y[i];
ans[1]=ok[1]=1;
for(ri i=2;i<=n;++i){
ll mxdis=-1,idx=-1;
for(ri j=1;j<=n;++j){
if(ok[j]) continue;
if(idx==-1||mxdis<(x[j]-x[ans[i-1]])*(x[j]-x[ans[i-1]])+(y[j]-y[ans[i-1]])*(y[j]-y[ans[i-1]])) mxdis=(x[j]-x[ans[i-1]])*(x[j]-x[ans[i-1]])+(y[j]-y[ans[i-1]])*(y[j]-y[ans[i-1]]),idx=j;
}
ans[i]=idx;ok[idx]=1;
}
for(ri i=1;i<=n;++i) cout<<ans[i]<<" ";
return 0;
}