牛客周赛 Round 89(A~G)
F想dp去了,F写完,G还有10分钟,只能感叹情况考虑不周了
A.小红开灯(一)
思路:签到,无需多言
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<cstring>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#include<bitset>
#define ll long long
// #define lowbit(x) (x & -x)
//#define endl "\n"// 交互题记得删除
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
ll ksm(ll x, ll y)//快速幂
{
ll ans = 1;
x %= mod;
while (y)
{
if (y & 1)
{
ans = ans * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return ans % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
ll lcm(ll x, ll y)
{
x /= gcd(x, y);
return y * x;
}
// inline ll read()//快读
// {
// register ll x = 0, f = 1;
// char c = getchar();
// while (c < '0' || c>'9')
// {
// if (c == '-') f = -1;
// c = getchar();
// }
// while (c >= '0' && c <= '9')
// {
// x = (x << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
// c = getchar();
// }
// return x * f;
// }
struct ss
{
ll v, id;
friend bool operator<(const ss& a, const ss& b)
{
return a.v < b.v;
};
};
void fio()//加速流
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为上下左右,后面四个为角落
int main()
{
fio();
ll t;
// t=1;
cin >> t;
while (t--)
{
ll n;
cin>>n;
cout<<(n+1)/2<<endl;
}
return 0;
}
B.小红开灯(二)
思路:只需考虑连续的1段即可,答案为每个1的连续段长度/2
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<cstring>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#include<bitset>
#define ll long long
// #define lowbit(x) (x & -x)
//#define endl "\n"// 交互题记得删除
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
ll ksm(ll x, ll y)//快速幂
{
ll ans = 1;
x %= mod;
while (y)
{
if (y & 1)
{
ans = ans * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return ans % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
ll lcm(ll x, ll y)
{
x /= gcd(x, y);
return y * x;
}
// inline ll read()//快读
// {
// register ll x = 0, f = 1;
// char c = getchar();
// while (c < '0' || c>'9')
// {
// if (c == '-') f = -1;
// c = getchar();
// }
// while (c >= '0' && c <= '9')
// {
// x = (x << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
// c = getchar();
// }
// return x * f;
// }
struct ss
{
ll v, id;
friend bool operator<(const ss& a, const ss& b)
{
return a.v < b.v;
};
};
void fio()//加速流
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为上下左右,后面四个为角落
int main()
{
fio();
ll t;
t=1;
// cin >> t;
while (t--)
{
ll n;
string f;
cin>>n>>f;
ll cnt=0;
ll ans=0;
for(ll i=0;i<f.size();i++)
{
if(f[i]=='1')
{
cnt++;
}
else
{
ans+=cnt/2;
cnt=0;
}
}
ans+=cnt/2;
cout<<ans<<endl;
}
return 0;
}
C.小红开灯(三,easy)
思路:简单dp,dp为灯数为i时的状态数,设dp[0]=1,可以认为灯为0也是一种情况,然后当k<i,时dp[i]=dp[i-1],你不能进行任何操作,所以答案得继承.当i>=k时,dp[i]=dp[i-1]*2,这里你可以认为以i为末尾时使用一次操作和不使用一次操作各创造了一种情况。此时乘2即可,不操作是继承,操作是在原来的基础上复制了一遍并改变了最后k个数。如此答案得出
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<cstring>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#include<bitset>
#define ll long long
// #define lowbit(x) (x & -x)
//#define endl "\n"// 交互题记得删除
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
ll ksm(ll x, ll y)//快速幂
{
ll ans = 1;
x %= mod;
while (y)
{
if (y & 1)
{
ans = ans * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return ans % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
ll lcm(ll x, ll y)
{
x /= gcd(x, y);
return y * x;
}
// inline ll read()//快读
// {
// register ll x = 0, f = 1;
// char c = getchar();
// while (c < '0' || c>'9')
// {
// if (c == '-') f = -1;
// c = getchar();
// }
// while (c >= '0' && c <= '9')
// {
// x = (x << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
// c = getchar();
// }
// return x * f;
// }
struct ss
{
ll v, id;
friend bool operator<(const ss& a, const ss& b)
{
return a.v < b.v;
};
};
void fio()//加速流
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为上下左右,后面四个为角落
int main()
{
fio();
ll t;
t=1;
// cin >> t;
while (t--)
{
ll n,k;
cin>>n>>k;
vector<ll>dp(n+5);
dp[0]=1;
for(ll i=1;i<=n;i++)
{
dp[i]=dp[i-1];
if(i>=k)dp[i]*=2;
dp[i]%=mod;
}
//cout<<dp[2]<<endl;
cout<<dp[n]<<endl;
}
return 0;
}
D.小红开灯(三,hard)
思路:k是随机改变的,不妨自己手动枚举下,k=n时,答案为2,这个不用说了。k是奇数时,答案就是2的n次方,否则答案就是2的n次方除以2。奇数可以想想我最后可以造成只改变一个数,所以在这基础上,我又可以单独改变一个数,所以什么答案都能创造出.偶数会发现某一时刻时,他只能创造一个关灯数为等差数列的可能情况,显然答案时2的n-1次方(可以手动枚举下)。
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<cstring>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#include<bitset>
#define ll long long
// #define lowbit(x) (x & -x)
//#define endl "\n"// 交互题记得删除
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
ll ksm(ll x, ll y)//快速幂
{
ll ans = 1;
x %= mod;
while (y)
{
if (y & 1)
{
ans = ans * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return ans % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
ll lcm(ll x, ll y)
{
x /= gcd(x, y);
return y * x;
}
// inline ll read()//快读
// {
// register ll x = 0, f = 1;
// char c = getchar();
// while (c < '0' || c>'9')
// {
// if (c == '-') f = -1;
// c = getchar();
// }
// while (c >= '0' && c <= '9')
// {
// x = (x << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
// c = getchar();
// }
// return x * f;
// }
struct ss
{
ll v, id;
friend bool operator<(const ss& a, const ss& b)
{
return a.v < b.v;
};
};
void fio()//加速流
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为上下左右,后面四个为角落
int main()
{
fio();
ll t;
t=1;
// cin >> t;
while (t--)
{
ll n,k;
cin>>n>>k;
vector<ll>f(n+5);
f[0]=1;
for(ll i=1;i<=n;i++)f[i]=f[i-1]*i%mod;
// vector<ll>dp(n+5);
// dp[0]=1;
// for(ll i=1;i<=n;i++)
// {
// dp[i]=dp[i-1];
// if(i>=k)dp[i]*=2;
// dp[i]%=mod;
// }
// //cout<<dp[2]<<endl;
// cout<<dp[n]<<endl;
if(n==k)
{
cout<<2<<endl;
}
else if(k&1)
{
cout<<ksm(2,n)<<endl;
}
else
{
//ll ans=
cout<<ksm(2,n-1)%mod<<endl;
}
}
return 0;
}
E.小红开灯(四)
思路:每次只能改变相邻位置的灯的状态,无非开灯数就加2或者不变,所以奇数必定无解。如何偶数情况?发现00可以直接转换为00,而10可以转换为01,这个相当于把0往左移动了,所以先处理每一行,从右到左把0移动到最左段,此时要么有个0,要么没有0。随后再从上到下对第一列进行刚刚类似的操作即可得出答案。
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<cstring>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#include<bitset>
#define ll long long
// #define lowbit(x) (x & -x)
//#define endl "\n"// 交互题记得删除
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
ll ksm(ll x, ll y)//快速幂
{
ll ans = 1;
x %= mod;
while (y)
{
if (y & 1)
{
ans = ans * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return ans % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
ll lcm(ll x, ll y)
{
x /= gcd(x, y);
return y * x;
}
// inline ll read()//快读
// {
// register ll x = 0, f = 1;
// char c = getchar();
// while (c < '0' || c>'9')
// {
// if (c == '-') f = -1;
// c = getchar();
// }
// while (c >= '0' && c <= '9')
// {
// x = (x << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
// c = getchar();
// }
// return x * f;
// }
struct ss
{
ll v, id;
friend bool operator<(const ss& a, const ss& b)
{
return a.v < b.v;
};
};
void fio()//加速流
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为上下左右,后面四个为角落
int main()
{
fio();
ll t;
t=1;
// cin >> t;
while (t--)
{
ll n,m;
cin>>n>>m;
string f[n+5];
ll cnt=0;
for(ll i=1;i<=n;i++)
{
cin>>f[i];
f[i]='0'+f[i];
for(ll j=1;j<=m;j++)
{
cnt+=(f[i][j]=='0');
}
}
if(cnt&1)cout<<-1<<endl;
else if(cnt==0)cout<<0<<endl;
else
{
vector<pair<ll,ll>>ans1,ans2;
ll cnt=0;
for(ll i=1;i<=n;i++)
{
cnt=0;
for(ll j=m;j>=1;j--)
{
if(f[i][j]=='0')
{
if(cnt)cnt=0,f[i][j]='1',f[i][j+1]='1',ans1.push_back({i,j}),ans2.push_back({i,j+1});
else cnt++;
}
else if(f[i][j]=='1')
{
if(cnt)f[i][j]='0',f[i][j+1]='1',ans1.push_back({i,j}),ans2.push_back({i,j+1});
else cnt=0;
}
}
}
cnt=0;
for(ll i=1;i<=n;i++)
{
if(f[i][1]=='0')
{
if(cnt)cnt=0,f[i][1]=f[i-1][1]='1',ans1.push_back({i,1}),ans2.push_back({i-1,1});
else cnt++;
}
else if(f[i][1]=='1')
{
if(cnt)f[i][1]='0',f[i-1][1]='1',ans1.push_back({i,1}),ans2.push_back({i-1,1});
else cnt=0;
}
}
cout<<ans1.size()<<endl;
for(ll i=0;i<ans1.size();i++)
{
cout<<ans1[i].first<<" "<<ans1[i].second<<" "<<ans2[i].first<<" "<<ans2[i].second<<endl;
}
}
}
return 0;
}
F.小红开灯(五,easy)
这道题是贪心题,一开始想dp去了,没看样例,有点惭愧。发现对于一个树如果其直径为2或者3都只要一次操作,所以直接dfs,然后回溯的时候看下最大长度是否为3,如果为3,再加一次答案,否则把最大深度进行回溯。注意如果回溯到根时,最大长度如果为2也是要进行一次操作的,至此答案得出。
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<cstring>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#include<bitset>
#define ll long long
// #define lowbit(x) (x & -x)
//#define endl "\n"// 交互题记得删除
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
ll ksm(ll x, ll y)//快速幂
{
ll ans = 1;
x %= mod;
while (y)
{
if (y & 1)
{
ans = ans * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return ans % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
ll lcm(ll x, ll y)
{
x /= gcd(x, y);
return y * x;
}
// inline ll read()//快读
// {
// register ll x = 0, f = 1;
// char c = getchar();
// while (c < '0' || c>'9')
// {
// if (c == '-') f = -1;
// c = getchar();
// }
// while (c >= '0' && c <= '9')
// {
// x = (x << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
// c = getchar();
// }
// return x * f;
// }
struct ss
{
ll v, id;
friend bool operator<(const ss& a, const ss& b)
{
return a.v < b.v;
};
};
void fio()//加速流
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为上下左右,后面四个为角落
vector<ll>g[100000+ 5];
int main()
{
fio();
ll t;
t = 1;
// cin >> t;
while (t--)
{
ll n;
cin >> n;
vector<vector<ll>>dp(n + 5, vector<ll>(2, 0));
for (ll i = 1; i < n; i++)
{
ll l, r;
cin >> l >> r;
g[l].push_back(r);
g[r].push_back(l);
}
//0关闭, 1开
ll ans = 0;
vector<bool>vis(n + 5);
function<ll(ll, ll, ll)>dfs = [&](ll x, ll f, ll sd)
{
ll ok = 0;
ll z;
ll cn2=0,cn3=0;
vector<ll>k;
ll u=0;
for (auto j : g[x])
{
if (j == f)continue;
else z=dfs(j,x,sd+1);
if(z-sd+1==2)cn2++;
else if(z-sd+1==3)cn3++;
u=max(u,z);
ok = 1;
}
if(ok==0)return sd;
if(x==1)
{
if(cn3>0)ans+=cn3;
else if(cn2>0)ans++;
return (ll)99;
}
else if(cn3==0)
{
return u;
}
else
{
ans+=cn3;
return sd-1;
}
};
ll d = dfs(1, 0, 1);
cout << ans << endl;
// cout<<min(dp[1][0],dp[1][1])<<endl;
}
return 0;
}
G.小红开灯(五,hard)
思路:F写出来之后,这道题就好写了。
还是按照F的思路想,但是注意下,我们可以开个数组去记录下此时距离这个结点最远的结点。如此如果当深度差为3时,先把当前结点,和深度差值为3的路上的儿子进行一次连接,后续把其他差值为3的路上的儿子和用数组记录其对应的结点进行一次连接。此时传递一个无用答案即可(记得做个标记,后续算答案时直接跳过它)。当此时结点为根结点时,需要特判深度差为3的结点为0且深度差为2的结点>0的情况。这时随便连一个深度差为2的结点即可。如果不需要进行操作,更新下此时结点的数组,然后传递最大深度和当前结点即可。具体看看我代码吧
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<cstring>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#include<bitset>
#define ll long long
// #define lowbit(x) (x & -x)
//#define endl "\n"// 交互题记得删除
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
ll ksm(ll x, ll y)//快速幂
{
ll ans = 1;
x %= mod;
while (y)
{
if (y & 1)
{
ans = ans * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return ans % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
ll lcm(ll x, ll y)
{
x /= gcd(x, y);
return y * x;
}
// inline ll read()//快读
// {
// register ll x = 0, f = 1;
// char c = getchar();
// while (c < '0' || c>'9')
// {
// if (c == '-') f = -1;
// c = getchar();
// }
// while (c >= '0' && c <= '9')
// {
// x = (x << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
// c = getchar();
// }
// return x * f;
// }
struct ss
{
ll v, id;
friend bool operator<(const ss& a, const ss& b)
{
return a.v < b.v;
};
};
void fio()//加速流
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为上下左右,后面四个为角落
vector<ll>g[100000+ 5];
int main()
{
fio();
ll t;
t = 1;
// cin >> t;
while (t--)
{
ll n;
cin >> n;
vector<vector<ll>>dp(n + 5, vector<ll>(2, 0));
for (ll i = 1; i < n; i++)
{
ll l, r;
cin >> l >> r;
g[l].push_back(r);
g[r].push_back(l);
}
//0关闭, 1开
//ll ans = 0;
vector<ll>vis(n + 5);
vector<pair<ll,ll>>ans;
function<pair<ll,ll>(ll, ll, ll)>dfs = [&](ll x, ll f, ll sd)
{
pair<ll,ll>z;
vector<pair<ll,ll>>k2,k3;
ll ok=0;
for(auto j:g[x])
{
if(j==f)continue;
else z=dfs(j,x,sd+1);
if(z.first==-1)continue;
if(z.first-sd+1==2)k2.push_back(z);
else if(z.first-sd+1==3)k3.push_back(z);
ok=1;
}
if(ok==0)
{
z={sd,x};
vis[x]=x;
return z;
}
if(k3.size()>0)
{
for(ll j=0;j<k3.size();j++)
{
if(j==0)
{
ans.push_back({x,k3[j].second});
}
else ans.push_back({k3[j].second,vis[k3[j].second]});
}
z={-1,1};
return z;
}
else if(k2.size()>0&&x==1)
{
ans.push_back({x,k2[0].second});
z={-1,-1};
return z;
}
else if(k2.size()==0)
{
z={sd,x};
vis[x]=x;
return z;
}
else
{
vis[x]=k2[0].second;
z={k2[0].first,x};
return z;
}
};
pair<ll,ll> d = dfs(1, 0, 1);
cout<<ans.size()<<endl;
for(auto &[x,y]:ans)cout<<x<<" "<<y<<endl;
}
return 0;
}

浙公网安备 33010602011771号