A.每次最多能把差缩小2*c克,向上取整
- #include <bits/stdc++.h>
- using namespace std;
- const int N = 2e5+10,mod=998244353;
- #define int long long
- using node=tuple<int,int,int,int>;
- typedef long long LL;
- typedef pair<int, int> PII;
-
- int n,m,q;
- int a[N];
- void solve()
- {
- int a,b,c;cin>>a>>b>>c;
- cout<<(abs(a-b)+2*c-1)/(2*c)<<"\n";
- }
- signed main() {
- cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
- int t=1;
- cin>>t;
- while(t--) solve();
-
- }
-
B.直接枚举每个格子能走多大
- #include <bits/stdc++.h>
- using namespace std;
- const int N = 2e5+10,M=2*N,mod=998244353;
- #define int long long
-
- typedef long long LL;
- typedef pair<int, int> PII;
- int a[N],b[N];
- int n, m;
-
- void solve()
- {
- cin>>n;
- for(int i=1;i<=n;i++){
- cin>>a[i]>>b[i];
- }
- int mx=1000000,mn=0;
- for(int i=1;i<=n;i++)
- {
- mx=min(mx,a[i]+((b[i]-1)/2));
- }
- cout<<mx<<"\n";
- }
- signed main() {
- cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
- int t=1;
- cin>>t;
- while(t--) solve();
-
- }
-
C.首先容易构造的是gcd=2,相当于是一个偶数/2,那么这种情况要特判
l==r,只能找他的质因子了,
- #include <bits/stdc++.h>
- using namespace std;
- const int N = 2e5+10,M=2*N,mod=998244353;
- #define int long long
-
- typedef long long LL;
- typedef pair<int, int> PII;
- int a[N],b[N];
- int n, m;
-
- void solve()
- {
- int l,r;cin>>l>>r;
- if(l==r)
- {
- for(int i=2;i<=l/i;i++){
- if(l%i==0){
- int x=l/i;
- cout<<x<<" "<<l-x<<"\n";
- return ;
- }
- }
- cout<<"-1\n";
- return ;
- }
- for(int i=l;i<=r;i++)
- {
- if(i%2==0&&i!=2){
- cout<<i/2<<" "<<i/2<<"\n";
- return ;
- }
- }
-
- cout<<"-1\n";
- }
- signed main() {
- cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
- int t=1;
- cin>>t;
- while(t--) solve();
-
- }
-
D.容斥原理
a+b-a*b,特判另一个数包含另一个数的集合就行
- #include <bits/stdc++.h>
- using namespace std;
- const int N = 2e5+10,M=2*N,mod=998244353;
- #define int long long
-
- typedef long long LL;
- typedef pair<int, int> PII;
- int a[N],b[N];
- int n, m;
- int gcd(int a, int b) // 欧几里得算法
- {
- return b ? gcd(b, a % b) : a;
- }
- int lcm(int a,int b){
- return a*b/gcd(a,b);
- }
- void solve()
- {
- cin>>n;
- int x,y;cin>>x>>y;
- if(x%y==0)
- { int z=n/y-n/x;
- cout<<-((z+1)*z)/2<<"\n";
- }
- else if(y%x==0)
- {
- int z=n/x-n/y;
- cout<<((n-z+1+n)*z)/2<<"\n";
- }
- else if(x!=1&&y!=1&&x!=y){
- int now=n/(lcm(x,y));
- int z=n/x-now;
- int res=(n-z+1+n)*z/2;
- z=n/y-now;
-
- res-=((z+1)*z)/2;
- cout<<res<<"\n";
- }
- else cout<<"-1\n";
- }
- signed main() {
- cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
- int t=1;
- cin>>t;
- while(t--) solve();
-
- }
-
E.直接线段树维护区间0的异或和 和 1的异或和,翻转操作就是互换而已
- #include <bits/stdc++.h>
- using namespace std;
- const int N = 2e5+10,mod=998244353;
- #define int long long
-
- typedef long long LL;
- typedef pair<int, int> PII;
- struct node{
- int l,r;
- int s0,s1,w,add;
- }tr[N*4];
- int n,m,q;
- int a[N],b[N];
- string s;
- void pushup(int u){
- tr[u].s0=tr[u<<1].s0^tr[u<<1|1].s0;
- tr[u].s1=tr[u<<1].s1^tr[u<<1|1].s1;
- }
- void pushdown(int u){
- if(tr[u].add){
- tr[u<<1].add^=1;
- tr[u<<1|1].add^=1;
- swap(tr[u<<1].s0,tr[u<<1].s1);
- swap(tr[u<<1|1].s0,tr[u<<1|1].s1);
- }
- tr[u].add=0;
- }
- void build(int u,int l,int r){
- tr[u]={l,r,0,0,0,0};
- if(l==r){
- tr[u].w=b[l];
- if(b[l]==1) tr[u].s1=a[l];
- else tr[u].s0=a[l];
- }
- else{
- int mid=l+r>>1;
- build(u<<1,l,mid);
- build(u<<1|1,mid+1,r);
- pushup(u);
- }
- }
- void modify(int u,int l,int r){
- if(tr[u].l>=l&&tr[u].r<=r)
- {
- tr[u].add^=1;
- swap(tr[u].s1,tr[u].s0);
- }
- else{
- pushdown(u);
- int mid=tr[u].l+tr[u].r>>1;
- if(l<=mid) modify(u<<1,l,r);
- if(r>mid) modify(u<<1|1,l,r);
- pushup(u);
- }
- }
- // node query(int u,int l,int r){
- // if(tr[u].l>=l&&tr[u].r<=r){
- // return tr[u];
- // }
- // else{
- // pushdown(u);
- // node res={0,0,0,0,0};
- // int mid=tr[u].l+tr[u].r>>1;
- // if(l<=mid){
- // res=query(u<<1,l,r);
- // }
- // if(r>mid) modify(u<<1|1,mid+1,r);
-
- // }
- // }
- void solve()
- {
- cin>>n;
- for(int i=1;i<=n;i++) cin>>a[i];
- cin>>s;
- s="?"+s;
- for(int i=1;i<=n;i++) b[i]=s[i]-'0';
- build(1,1,n);
- int q;cin>>q;
- while(q--){
- int op;
- cin>>op;
- if(op==1){
- int l,r;cin>>l>>r;
- modify(1,l,r);
- }
- else{
- int x;cin>>x;
- if(x==1) cout<<tr[1].s1<<" ";
- else cout<<tr[1].s0<<" ";
- }
- }
- cout<<"\n";
- }
- signed main() {
- cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
- int t=1;
- cin>>t;
- while(t--) solve();
-
- }
-
F.画图样例其实可以知道,按照拓扑序直接处理即可,最后会有多个环,每个环的贡献最大是让一个点贡献不能*2,其他都可以
我写的比较麻烦,先拓扑序把不是环的点先存了,再把每个环tarjan缩点,然后单独处理每个环,每个环算完出发点后又dfs存答案0.0
所以用了dfs+拓扑排序+tarjan
- #include <bits/stdc++.h>
- using namespace std;
- const int N = 2e5+10,M=2*N,mod=998244353;
- #define int long long
-
- typedef long long LL;
- typedef pair<int, int> PII;
- int a[N],b[N];
- int n, m;
- int G[N];
- int dfn[N], low[N], timestamp;
- int stk[N], top;
- bool in_stk[N],Size[N];
- int id[N], scc_cnt;
- vector<int> g[N];
- int din[N],dout[N];
- void tarjan(int u)
- {
- dfn[u] = low[u] = ++ timestamp;
- stk[ ++ top] = u, in_stk[u] = true;
-
- int j = G[u];
- if (!dfn[j])
- {
- tarjan(j);
- low[u] = min(low[u], low[j]);
- }
- else if (in_stk[j]) low[u] = min(low[u], dfn[j]);
-
-
- if (dfn[u] == low[u])
- {
- ++ scc_cnt;
- int y;
- do {
- y = stk[top -- ];
- in_stk[y] = false;
- id[y] = scc_cnt;
-
- } while (y != u);
- }
- }
- void solve()
- {
- cin>>n;
- top=timestamp=scc_cnt=0;
- for(int i=0;i<=n;i++){
- G[i]=0;
- g[i].clear();
- low[i]=dfn[i]=id[i]=0;
- in_stk[i]=false;
- din[i]=dout[i]=0;
-
- }
- for(int i=1;i<=n;i++){
- cin>>a[i];
- G[i]=a[i];
- din[a[i]]++;
- }
- for(int i=1;i<=n;i++) cin>>b[i];
- for(int i=1;i<=n;i++)
- {
- if(!dfn[i]) tarjan(i);
- }
- queue<int> q;
- vector<int> res;
- for(int i=1;i<=n;i++) if(din[i]==0) q.push(i);
- while(q.size()){
- auto t=q.front();
- q.pop();res.push_back(t);
- int v=G[t];
- if(--din[v]==0){
- q.push(v);
- }
- }
-
- for(int i=1;i<=n;i++){
-
- g[id[i]].push_back(i);
- }
-
- vector<bool> st(n+10,false);
- function<void(int)> dfs=[&](int u){
- if(st[u]) return ;
- st[u]=true;
- res.push_back(u);
- dfs(G[u]);
- };
-
- for(int i=1;i<=scc_cnt;i++)
- {
- if(g[i].size()==1) continue;
- else{
- sort(g[i].begin(),g[i].end());
- m=g[i].size();
- int now=0,mx=0,idx=0;
-
- for(auto x:g[i]) now+=2*b[x];
- for(int x:g[i])
- {
- if(mx<now-b[x]) idx=x,mx=max(mx,now-b[x]);
- }
- dfs(G[idx]);
- }
- }
- for(auto x:res) cout<<x<<" ";
- cout<<"\n";
-
- }
- signed main() {
- cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
- int t=1;
- cin>>t;
- while(t--) solve();
-
- }
-
G.首先把左右两边的1去掉没用,
然后思考中间的值,因为处理完后左右两边一定不是1,所以如果区间乘大于1e9
说明至少有60个2相乘,那么中间的1肯定也只能要
然后如果不大于
那么说明中间区间的数加起来不大于60(去掉中间是1的数)
那么直接枚举左右端点即可
- #include <bits/stdc++.h>
- using namespace std;
- const int N = 2e5+10,M=2*N,mod=998244353;
- #define int long long
-
- typedef long long LL;
- typedef pair<int, int> PII;
- int a[N],b[N];
- int n, m;
-
- void solve()
- {
- cin>>n;
- for(int i=1;i<=n;i++) cin>>a[i];
- int l=1,r=n;
- while(a[l]==1&&l<r){
- l++;
- }
- while(a[r]==1&&l<r){
- r--;
- }
- int res=1;
- for(int i=l;i<=r;i++){
- res*=a[i];
- if(res>1e9){
- cout<<l<<" "<<r<<"\n";
- return ;
- }
- }
- int idx=0,sum=0;
- for(int i=1;i<=n;i++){
- if(a[i]>1) b[++idx]=i;
- sum+=a[i];
- }
- int ans=sum,ansl=1,ansr=1;
- for(int i=1;i<=idx;i++){
- res=1;
- l=b[i];
- int s=0;
- for(int j=i;j<=idx;j++){
- res*=a[b[j]];
- r=b[j];
- s+=a[b[j]];
- int val=sum-s-(r-l+1-(j-i+1))+res;
- if(val>ans){
- ans=val;
- ansl=l,ansr=r;
- }
- }
- }
- cout<<ansl<<" "<<ansr<<"\n";
- }
- signed main() {
- cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
- int t=1;
- cin>>t;
- while(t--) solve();
-
- }
-