牛客周赛 Round 103 (全解)
不太想做牛客周赛的题解,毕竟题解很快就给出了。这次写是为了警示我以后都用自然溢出去hash
A.清楚
思路:判断最后一位是不是0即可
#include<iostream>
#include<queue>
#include<map>
#include<iomanip>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll long long
#define ull unsigned long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return ans % mod;
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
int main(){
fio();
ll t=1;
// cin>>t;
while(t--){
ll n;
cin>>n;
if(n-n/10*10==0)cout<<"NO"<<endl;
else cout<<"YES"<<endl;
}
return 0;
}
B.姐姐
思路:全相同最好判断,随后就是只要判断连续0或连续1在环中是连续的即可,直接倍增,将链变环.走一遍看看即可
#include<iostream>
#include<queue>
#include<map>
#include<iomanip>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll long long
#define ull unsigned long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return ans % mod;
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
int main(){
fio();
ll t=1;
cin>>t;
while(t--){
ll n;
cin>>n;
vector<ll>a(2*n+4);
ll cnt=0;
ll c=0;
for(ll i=1;i<=n;i++)cin>>a[i],cnt+=(a[i]==a[1]),c+=(a[i]==1);
// for(ll i=n)
if(cnt==n)cout<<"YES"<<endl;
else {
for(ll i=n+1;i<=2*n;i++)a[i]=a[i-n];
ll len=c;
bool f=0;
for(ll i=1;i<=n*2;i++){
if(a[i])len--;
else len=c;
if(len==0){
f=1;
break;
}
}
cout<<(f==1?"YES":"NO")<<endl;
}
}
return 0;
}
C.智乃
思路:手枚举下,不完全归纳得出答案为2^(n-1).
#include<iostream>
#include<queue>
#include<map>
#include<iomanip>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll long long
#define ull unsigned long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return ans % mod;
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
int main(){
fio();
ll t=1;
// cin>>t;
while(t--){
ll n;
cin>>n;
// vector<ll>a(2*n+4);
cout<<ksm(2,n-1)<<endl;
}
return 0;
}
D.哥哥
思路:先看有没有至少三个(答案为0)。然后看有没有两个(答案为1),然后看有没有一个(答案为1或2,走一遍试试看看能不能一次操作解决即可(能就1否则就2)),如果都没有直接2次
#include<iostream>
#include<queue>
#include<map>
#include<iomanip>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll long long
#define ull unsigned long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return ans % mod;
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
int main(){
fio();
ll t=1;
cin>>t;
while(t--){
ll n;
string f;
cin>>n>>f;
ll cnt=0;
for(ll i=0;i<f.size();i++){
cnt+=(f[i]==f[0]);
}
if(cnt==n){
cout<<2<<endl;
}
else {
cnt=0;
for(ll i=1;i<f.size();i++){
if(f[i]!=f[i-1])cnt++;
}
if(cnt>=3)cout<<0<<endl;
else {
ll ans=0;
for(ll i=0;i<f.size();i++){
bool flag=0;
if(i>0){
if(f[i]!=f[i-1])flag=1;
}
if(i<f.size()-1){
if(f[i]!=f[i+1])flag=1;
}
if(flag==0){
ll cc=0;
if(i>0)cc++;
if(i<f.size()-1)cc++;
ans=max(ans,cnt+cc);
}
}
if(ans<=2)cout<<2<<endl;
else cout<<1<<endl;
}
}
}
return 0;
}
E.新婚
思路:如果从一个点往上走会比较好想,最多走个21 * n次,然后记录下这个路径上的二进制,然后倒着和正着扫一遍(注意不要越界哦),打上标记即可.查询O(q)
#include<iostream>
#include<queue>
#include<map>
#include<iomanip>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll long long
#define ull unsigned long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9 + 7;
ll ksm(ll x, ll y)
{
ll ans = 1;
while (y)
{
if (y & 1)
{
ans = ans * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return ans % mod;
}
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
int main(){
fio();
ll t=1;
// cin>>t;
while(t--){
ll n,q;
cin>>n>>q;
string f;
cin>>f;
f='0'+f;
vector<vector<ll>>g(n+2);
vector<ll>fa(n+2);
for(ll i=1;i<n;i++){
ll l,r;
cin>>l>>r;
g[l].push_back(r);
g[r].push_back(l);
}
vector<bool>vis((1ll<<20)+1,0);
function<void(ll,ll)>dfs=[&](ll x,ll fc){
fa[x]=fc;
ll len=21;
ll now=x;
vector<ll>ls;
while(len--){
if(now==0)break;
ls.push_back((f[now]=='1'));
now=fa[now];
ll c1=0,c2=0;
ll l=1;
for(ll i=0;i<ls.size();i++){
c1+=ls[i]*l;
c2+=ls[ls.size()-i-1]*l;
l<<=1;
}
if(c1<=(1ll<<20))vis[c1]=1;
if(c2<=(1ll<<20))vis[c2]=1;
// vis[c1]=vis[c2]=1;
}
for(auto j:g[x]){
if(j==fc)continue;
else dfs(j,x);
}
};
dfs(1,0);
// cout<<
while(q--){
ll x;
cin>>x;
cout<<(vis[x]?"YES":"NO")<<endl;
}
}
return 0;
}
F.快乐
思路:hash,显然最长公共前缀的贡献,可以等价于该前缀的前缀连续子串的出现次数。所以先hash一遍求出所有前缀连续字串的出现次数,然后再走一遍做m个字符串前缀连续字串贡献累加。最后对目标串进行字符串hash,随后根据对应字符串hash求法(直接查段值),遍历+二分,找当前左端点能有值的最右端点即可。(用自然溢出,不用取模会更快,还有就是用数组的二分会比map更快)
吐槽:赛时不用自然溢出,经历了Wa和Tle
#include<iostream>
#include<queue>
#include<map>
#include<iomanip>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#include<functional>
#define ll long long
#define ull unsigned long long
#define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
using namespace std;
mt19937 rnd(time(0));
// const ll mod = 1e9 + 7;
const ull p=1145161651561;
// ll ksm(ll x, ll y)
// {
// ll ans = 1;
// while (y)
// {
// if (y & 1)
// {
// ans = ans * x % mod;
// }
// x = x * x % mod;
// y >>= 1;
// }
// return ans % mod;
// }
void fio()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
int main(){
fio();
int t=1;
cin>>t;
while(t--){
int n,m;
cin>>n>>m;
string str,f[m+2];
cin>>str;
str='0'+str;
map<ull,ll>mp;
for(int i=1;i<=m;i++){
cin>>f[i];
ull hash=0;
for(int j=0;j<f[i].size();j++){
hash=hash*p+f[i][j];
mp[hash]++;
}
}
map<ull,ll>an;
vector<ull>dd;
for(int i=1;i<=m;i++){
ull hash=0;
ll pre=0;
for(int j=0;j<f[i].size();j++){
hash=hash*p+f[i][j];
pre+=mp[hash];
if(an.find(hash)==an.end()){
dd.push_back(hash);
an[hash]=pre;
}
}
}
sort(dd.begin(),dd.end());
ull hash=0;
vector<ull>pre(n+5,0);
for(int i=1;i<str.size();i++){
hash=hash*p+str[i];
pre[i]=hash;
}
vector<ull>us(n+5);
us[0]=1;
for(ll i=1;i<=n;i++){
us[i]=us[i-1]*p;
}
function<ll(int,int)>ck=[&](int x,int y){
ull ans=pre[y]-pre[x-1]*us[y-(x-1)];
ll j=lower_bound(dd.begin(),dd.end(),ans)-dd.begin();
if(j!=dd.size()&&dd[j]==ans)return 1ll;
else return 0ll;
};
ll ans=0;
for(int i=1;i<str.size();i++){
int l=i,r=str.size()-1;
while(l<=r){
int mid=l+r>>1;
if(ck(i,mid)){
l=mid+1;
}
else r=mid-1;
}
ull ac=pre[r]-pre[i-1]*us[r-(i-1)];
ans=max(ans,an[ac]);
}
cout<<ans<<endl;
}
return 0;
}

浙公网安备 33010602011771号