题目讲解:牛客周赛39讲题直播回放_哔哩哔哩_bilibili
题号 | 标题 | 已通过代码 | 通过率 | 我的状态 |
---|---|---|---|---|
A | 小红不想做炸鸡块粉丝粉丝题 | 点击查看 | 1978/2610 | 未通过 |
B | 小红不想做鸽巢原理 | 点击查看 | 1172/8606 | 未通过 |
C | 小红不想做完全背包(easy) | 点击查看 | 1261/3574 | 未通过 |
D | 小红不想做完全背包 (hard) | 点击查看 | 416/5728 | 未通过 |
E | 小红不想做莫比乌斯反演杜教筛求因子和的前缀和 | 点击查看 | 557/3456 | 未通过 |
F | 小红不想做模拟题 | 点击查看 | 346/1750 | 未通过 |
G | 小红不想做平衡树 | 点击查看 | 31/3150 | 未通过 |
B.小红不想做鸽巢原理
思路:贪心,由于最后一定会剩下sum%k个球,我们想让球的颜色最少,最好的方法是让剩下的球全部是一个颜色的。所以先求一下sum%k看剩几个球,再对数组排序,倒着取看结果是否为负,若为负则表示当前颜色是不能取完的(很直觉的做法,感觉也可以从前往后进行模拟,比较符合正常思路)。
#include<bits/stdc++.h>
using namespace std;
int main(){long long n,k,sum=0;cin>>n>>k;vector<long long> a(n+1);for(int i=1;i<=n;i++){cin>>a[i];sum+=a[i];}sort(a.begin()+1,a.end());sum %= k;long long cnt = 0;for(int i=n;i;i--){if(sum<=0){cout<<cnt<<endl;return 0;}sum-=a[i];cnt++;}cout<<n<<endl;return 0;
}
C&D.小红不想做完全背包
思路:dp。dp[i]表示%p后能凑出i这个数字使用最少的数字的个数。dp是考虑从哪个状态枚举到哪个状态。但好像没讲全对,可能是状态转移的更新部分不太对。本题也可以使用bfs解决,感觉很妙。
正确的dp代码:代码查看 (nowcoder.com)
以下是bfs的正确代码。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int f[2000+10],vis[2000+10];
int main()
{int n,p;cin>>n>>p;ll a[n+10];queue<pair<ll,ll>>q;for(int i=1;i<=n;i++){cin>>a[i];if(f[a[i]%p]==0){f[a[i]%p]=1;q.push({a[i]%p,1});vis[a[i]%p]=1;}}while(q.size()){ll x=q.front().first,y=q.front().second;if(x==0){cout<<y<<endl;return 0;}for(int i=0;i<p;i++){if(f[i]==1&&vis[(i+x)%p]==0){q.push({(i+x)%p,y+1});vis[(i+x)%p]=1;}}q.pop();}return 0;
}
E.小红不想做莫比乌斯反演杜教筛求因子和的前缀和
思路:推公式,不是很难,题目完全是在迷惑大家。
#include<bits/stdc++.h>
using namespace std;int main() {int n, m, p, x;cin >> n >> m >> p >> x;int ans = 0;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(x-i*j<=0) continue;int up = x-i*j,down = (2*(i+j));if(up%down!=0) continue;int h = up/down;if(h<=p) ans++;}}cout<<ans<<endl;return 0;
}
F.小红不想做模拟题
思路:带懒标记的线段树。
#include<bits/stdc++.h>
#define lc u<<1
#define rc u<<1|1
using namespace std;
int n,q,a[101010],b[101010];
struct node{int l,r,c1,c2,c;int lz1,lz2;
}tr[404040];
void push_up(int u){tr[u].c1 = tr[lc].c1+tr[rc].c1;tr[u].c2 = tr[lc].c2+tr[rc].c2;tr[u].c = tr[lc].c+tr[rc].c;
}
void build(int u,int l,int r){tr[u] = {l,r,a[l],b[l],a[l]&b[l]};if(l==r) return;int mid = l+r>>1;build(lc,l,mid);build(rc,mid+1,r);push_up(u);
}
void push_down(int u){if(tr[u].lz1){int lz = tr[u].lz1;tr[lc].c1 = tr[lc].r - tr[lc].l + 1;tr[lc].c = tr[lc].c2;tr[rc].c1 = tr[rc].r - tr[rc].l + 1;tr[rc].c = tr[rc].c2;tr[rc].lz1 = 1;tr[lc].lz1 = 1;tr[u].lz1 = 0;}if(tr[u].lz2){int lz = tr[u].lz2;tr[lc].c2 = tr[lc].r - tr[lc].l + 1;tr[lc].c = tr[lc].c1;tr[rc].c2 = tr[rc].r - tr[rc].l + 1;tr[rc].c = tr[rc].c1;tr[rc].lz2 = 1;tr[lc].lz2 = 1;tr[u].lz2 = 0;}
}
void modify(int u,int l,int r,int op){if(l<=tr[u].l&&tr[u].r<=r){if(op==1){tr[u].c1 = tr[u].r - tr[u].l +1;tr[u].c = tr[u].c2;tr[u].lz1 = 1;}else{tr[u].c2 = tr[u].r - tr[u].l +1;tr[u].c = tr[u].c1;tr[u].lz2 = 1;}return;}push_down(u);int mid = tr[u].l+tr[u].r>>1;if(l<=mid) modify(lc,l,r,op);if(r>mid) modify(rc, l, r, op);push_up(u);
}
int main(){string A,B;cin>>n>>A>>B>>q;int ans = 0;for(int i=0;i<n;i++){a[i+1] = A[i] - '0';b[i+1] = B[i] - '0';}build(1,1,n);while(q--){char op;int l,r;cin>>op>>l>>r;int x = op-'A'+1;modify(1, l, r, x);cout<<tr[1].c<<endl;}return 0;
}