Gym102956 partial solution

Keywords: gym

Contest Link

Take more.

catalogue

Thank you@ hht2005 Help.

B. Beautiful Sequence Unraveling

Define a good sequence with a length of \ (n \) \ (a \) is a sequence in which there is no position \ (1 \ le I < n \) such that \ (\ max\{a_1,\ldots,a_i\}=\min\{a_{i+1},\ldots,a_n \} \).
Count the good sequence with length of \ (n \) and value range of \ ([1,k] \), modulo \ (p \) and output.
\(1\le n\le 400\),\(1\le k\le 10^8\),\(998244353\le p\le 10^9+9\),\(p\in\text{prime}\).

Solution

\(k \) is yours, if you consider the direct coolness related to \ (k \).
Considering avoiding \ (k \), it is not difficult to find that there are only \ (n \) different numbers in the legal sequence, which is directly discretized.
Consider that \ (f_{i,j} \) represents a sequence with a length of \ (I \) and the number of good sequences with a value range of \ ([1,j] \).
A good sequence is not easy to find, but considering a bad sequence \ (a \), set its maximum position \ (P \) so that \ (\ max\{a_1,\ldots,a_p\}=\min\{a_{p+1},\ldots,a_n \} \), it is easy to find a big property: \ (a_{p+1},\ldots,a_n \) is a good sequence. If it is not a good sequence, \ (P \) is not the maximum.
Enumerating the maximum position \ (p \) and enumerating its value \ (m \) can get the DP formula:

\[f_{i,j}=j^i-\sum^{i-1}_{p=1}\sum^j_{m=1}(m^p-(m-1)^p)(f_{i-p,j-m+1}-f_{i-p,j-m}) \]

\ (O(n^3) \) can be achieved using prefixes and optimizations.
Consider setting \ (g_, I \) to represent the sequence with length of \ (n \), and the number of good sequences with value range of \ ([1,i] \):

\[g_i=f_{n,i}-\sum^{i-1}_{j=1}\binom i j g_j \]

So the answer is: \ (\ displaystyle \ sum ^ n {I = 1} \ BINOM k i g u I \).
Combination number calculation, time complexity \ (O(n^3) \).

Code
const int N=400;
int n,K,mod,f[N+10][N+10],ans,g[N+10],sum[N+10][N+10][N+10];
void Add(int &x,int y) {
    x+=y;
    if(x>=mod) x-=mod;
}
void Del(int &x,int y) {
    x-=y;
    if(x<0) x+=mod;
}
int fpow(int x,int y) {
    int ret=1;
    for(;y;y>>=1) {
        if(y&1) ret=1ll*ret*x%mod;
        x=1ll*x*x%mod;
    }
    return ret;
}
int C(int n,int m) {
    int ret=1,fm=1;
    for(int i=n;i>=n-m+1;i--) ret=1ll*ret*i%mod;
    for(int i=1;i<=m;i++) fm=1ll*fm*i%mod;
    return 1ll*ret*fpow(fm,mod-2)%mod;
}
//n!/(n-m)!/m!
int po[N+10][N+10],inv[N+10][N+10];
void init() {
    for(int i=1;i<=n;i++) {
        po[i][0]=inv[i][0]=1;
        inv[i][1]=fpow(po[i][1]=i,mod-2);
        for(int j=2;j<=n;j++) po[i][j]=1ll*po[i][j-1]*i%mod,inv[i][j]=1ll*inv[i][j-1]*inv[i][1]%mod;
    }
}
int main() {
    n=read(),K=read(),mod=read();
    init();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++) {
            f[i][j]=po[j][i];
            for(int t=1;t<=j;t++) {
                int A=po[t][i],B=po[t-1][i];
                int sum1=(sum[i-1][j-t][t]-sum[i-1][j-t+1][t]+mod)%mod;
                int sum2=(sum[i-1][j-t+1][t-1]-sum[i-1][j-t][t-1]+mod)%mod;
                Add(f[i][j],(1ll*A*sum1%mod+1ll*B*sum2%mod)%mod);
            }
            for(int t=1;t<=n;t++) sum[i][j][t]=(sum[i-1][j][t]+1ll*f[i][j]*inv[t][i]%mod)%mod;
        }
    for(int i=1;i<=n;i++) {
        g[i]=f[n][i];
        for(int j=1;j<i;j++) Del(g[i],1ll*C(i,j)*g[j]%mod);
    }
    for(int i=1;i<=n;i++) Add(ans,1ll*C(K,i)*g[i]%mod);
    write((ans+mod)%mod),enter;
    return WDNMD;
}

C. Brave Seekers of Unicorns

Defining a good sequence satisfies the following conditions:

  • The sequence is not empty.
  • There are no three consecutive elements exclusive or and \ (= 0 \).
  • Sequence increment.
  • The value range of the sequence is \ ([1,n] \).

Given \ (n \), count the good sequence, and take the module for the answer \ (998244353 \).

Solution

Let \ (f_i \) represent the number of all schemes ending with \ (I \), including:

\[f_i=\sum^{i-1}_{j=1}f_j-[j\oplus i<j]f_{j\oplus i} \]

\(f_j \) can be prefixed and taken away by one wave. Considering the later, it can be deformed into \ (\ sum_ {K < K \ oplus I < I} f_k \).
Considering the case of \ (i\oplus j\oplus k=0 \), there are only two \ (1 \) at most in a bit. Enumerate the highest \ (1 \) bit \ (d \) of \ (i \) in the binary system. It is determined that the \ (d \) bit of \ (j \) is \ (1 \) and the \ (d \) bit of \ (K \) is \ (0 \), so the \ (d \) bit can be arbitrarily taken in the future.
Then the range of \ (k \) is \ ([2^d,2^{d+1}-1] \), which can also be prefixed and combined.
Time complexity \ (O(n\log n) \).

Code
const int N=1e6,mod=998244353;
ll f[N+10],n,sum[N+10];
int main() {
    scanf("%d",&n);
    f[1]=1;sum[1]=1;
    for(int i=2;i<=n;i++) {
        f[i]=sum[i-1]+1;
        int j;
        for(j=20;j>=0;j--)
            if(i&(1<<j)) break;
        j--;
        for(;j>=0;j--) if(i&(1<<j)) f[i]=(f[i]-sum[(1<<(j+1))-1]+sum[(1<<j)-1]+mod)%mod;
        sum[i]=(f[i]+sum[i-1])%mod;
    }
    printf("%lld\n",sum[n]%mod);
}

D. Bank Security Unification

Take a subsequence from a sequence \ (a \) with a length of \ (n \), so that the sum of bitwise and values of two adjacent elements is the largest.

\(2\le n\le 10^6\),\(0\le a_i\le 10^{12}\).

Solution

We want the bitwise and maximum, that is, we want the binary digits of two adjacent elements to be as same as possible.
Consider that \ (f_i \) represents the maximum answer of the subsequence with the last bit of \ (I \), and the naive transfer is \ (O(n^2) \).
Consider pruning. If we consider the current one, where do we want to transfer from, it is obviously the same bit. If we choose these bits later, they must be better than those in the front.
Therefore, the record \ (las_{i,0/1} \) indicates where the last one in the \ (I \) bit is \ (0 / 1 \), which is only transferred from the corresponding \ (Las \) each time.
Time complexity \ (O(n\log a_i) \).

Code
const int N=1e6;
int n;
ll f[N+10],g[N+10],ans;
int las[44][2];
int main() {
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%lld",&f[i]);
    g[2]=(f[1]&f[2]);
    for(int i=1;i<=2;i++)
        for(int j=39;j>=0;j--)
            if(f[i]&(1ll<<j)) las[j][1]=i;
            else las[j][0]=i;
    for(int i=3;i<=n;i++) {
        for(int j=39;j>=0;j--) {
            int zz=(bool)(f[i]&(1ll<<j));
            g[i]=max(g[i],g[las[j][zz]]+(f[las[j][zz]]&f[i]));
        }
        for(int j=39;j>=0;j--)
            if(f[i]&(1ll<<j)) las[j][1]=i;
            else las[j][0]=i;
    }
    for(int i=1;i<=n;i++) ans=max(ans,g[i]);
    printf("%lld\n",ans);
}

E. Brief Statements Union

Given \ (n \) numbers, \ (k \) restrictions, such as \ (a_l \ and a {L + 1} \ and \ ldots \ and a {r} = x \).

For a certain restriction, if the restriction can be deleted so that there is a sequence satisfying the condition, it is said to be good.

Output which sequences are good and which sequences are bad.

\(1\le n,k\le 10^6\),\(0\le x_i\le 10^{18}\).

Solution

Considering by bit, the remaining restrictions are divided into two categories: \ (1 \) restrictions and \ (0 \) restrictions.
Override the \ (1 \) limit and consider the number of conflicts with the \ (0 \) limit:

  • Is \ (0 \): all OK.
  • For \ (1 \): the conflict is an insider, knife.
  • \(> 1 \): not at all.

\(0 \) limit is considered.
Consider how to delete the \ (1 \) limit. For each point that is only covered by the \ (1 \) limit once, we can delete this \ (1 \) limit to meet several \ (0 \) limits.
For a certain \ (0 \) restriction, we will remove the \ (1 \) restriction that can be deleted, take out the \ (1 \) restriction that legalizes the \ (0 \) restriction, and cross such a set of all \ (0 \) restrictions.
\ (O(n\log x_i) \) can be achieved by using difference.

Code
const int N=1e6;
int n,K;
int ql[N+10],qr[N+10];
ll qx[N+10],f[N+10],g[N+10];
int nxt[N+10],pre[N+10],ans[N+10];
int vio[N+10],tot,id,pos[N+10],seg[N+10];
int main() {
    scanf("%d %d",&n,&K);
    for(int i=1;i<=K;i++) scanf("%d %d %lld",&ql[i],&qr[i],&qx[i]);
    nxt[n+1]=n+1,pre[0]=0;
    for(int k=0;k<60;k++) {
        for(int i=1;i<=n;i++) f[i]=g[i]=0;
        for(int i=1;i<=K;i++)
            if((1ll<<k)&qx[i])
                f[ql[i]]++,f[qr[i]+1]--,
                g[ql[i]]+=i,g[qr[i]+1]-=i;
        for(int i=1;i<=n;i++) f[i]+=f[i-1],g[i]+=g[i-1];
        for(int i=n;i>=1;i--) nxt[i]=f[i]?nxt[i+1]:i;
        id=tot=0;
        for(int i=1;i<=K;i++)
            if(!((1ll<<k)&qx[i]))
                if(nxt[ql[i]]>qr[i])
                    vio[++tot]=i;
        if(tot==0) {
            for(int i=1;i<=K;i++) ans[i]++;
            continue;
        }
        if(tot==1) ans[vio[1]]++;
        for(int i=1;i<=n;i++)
            if(f[i]==1&&!pos[g[i]])
                seg[pos[g[i]]=++id]=g[i];
        for(int i=1;i<=n;i++) pre[i]=(f[i]==1)?i:pre[i-1];
        for(int i=n;i>=1;i--) nxt[i]=(f[i]==1)?i:nxt[i+1];
        int l=0,r=id;
        for(int i=1;i<=tot;i++) {
            int u=vio[i];
            if(nxt[ql[u]]<=qr[u]) l=max(l,pos[g[nxt[ql[u]]]]);
            else l=id+1;
            if(pre[qr[u]]>=ql[u]) r=min(r,pos[g[pre[qr[u]]]]);
            else r=0;
        }
        for(int i=l;i<=r;i++) ans[seg[i]]++;
        for(int i=1;i<=K;i++) pos[i]=0;
    }
    for(int i=1;i<=K;i++)
        if(ans[i]==60) putchar('1');
        else putchar('0');
    puts("");
}

F. Border Similarity Undertaking

Given a letter rectangle, find out how many sub rectangles it has to satisfy that all the surrounding characters are the same.

\(1\le n,m\le 2000\).

Solution

Consider matrix divide and conquer, that is, divide and conquer the length and width of a matrix.
Divide and conquer each matrix, and consider calculating the number of matrices across the centerline.
This process can preprocess the extension distance of a point up, down, left and right, which can be dealt with violently.
The left and right sides of the center line are processed respectively to process the number of rectangles that can be formed on the left and right sides.
The code is more detailed and complex, with time complexity \ (O(nm\log n) \).

Code
const int N=2000;
int n,m;
char ch[N+10][N+10];
int up[N+10][N+10],dn[N+10][N+10],lef[N+10][N+10],rig[N+10][N+10];
int al[N+10][N+10],ar[N+10][N+10];
ll ans;
void solve(int l1,int r1,int l2,int r2) {
    if(l1==r1||l2==r2) return;
    if(r1-l1+1<=r2-l2+1) {
        int mid=(r2+l2)>>1,L,R;
        for(int i=l1;i<=r1;i++)
            for(int j=l1;j<=r1;j++)
                al[i][j]=ar[i][j]=0;
        for(int i=l1;i<=r1;i++) {
            for(int j=mid;j>=l2&&j>=lef[i][mid];j--)
                al[i][min(dn[i][j],r1)]++,
                al[i][max(up[i][j],l1)]++;
            for(int j=r1-1;j>=i;j--) al[i][j]+=al[i][j+1];
            for(int j=l1+1;j<=i;j++) al[i][j]+=al[i][j-1];
            for(int j=mid+1;j<=r2&&j<=rig[i][mid+1];j++) 
                ar[i][min(dn[i][j],r1)]++,
                ar[i][max(up[i][j],l1)]++;
            for(int j=r1-1;j>=i;j--) ar[i][j]+=ar[i][j+1];
            for(int j=l1+1;j<=i;j++) ar[i][j]+=ar[i][j-1];
        }
        for(int i=l1;i<=r1;i++)
            for(int j=i+1;j<=r1;j++) {
                if(ch[i][mid]!=ch[j][mid]) continue;
                if(ch[i][mid]!=ch[i][mid+1]) continue;
                if(ch[j][mid]!=ch[j][mid+1]) continue;
                L=lef[i][mid]>=lef[j][mid]?al[i][j]:al[j][i];
                R=rig[i][mid+1]<=rig[j][mid+1]?ar[i][j]:ar[j][i];
                ans+=1ll*L*R;
            }
        solve(l1,r1,l2,mid);
        solve(l1,r1,mid+1,r2);
    }
    else {
        int mid=(l1+r1)>>1,L,R;
        for(int i=l2;i<=r2;i++)
            for(int j=l2;j<=r2;j++)
                al[i][j]=ar[i][j]=0;
        for(int i=l2;i<=r2;i++) {
            for(int j=mid;j>=l1&&j>=up[mid][i];j--)
                al[i][min(rig[j][i],r2)]++,
                al[i][max(lef[j][i],l2)]++;
            for(int j=r2-1;j>=i;j--) al[i][j]+=al[i][j+1];
            for(int j=l2+1;j<=i;j++) al[i][j]+=al[i][j-1];
            for(int j=mid+1;j<=r1&&j<=dn[mid+1][i];j++)
                ar[i][min(rig[j][i],r2)]++,
                ar[i][max(lef[j][i],l2)]++;
            for(int j=r2-1;j>=i;j--) ar[i][j]+=ar[i][j+1];
            for(int j=l2+1;j<=i;j++) ar[i][j]+=ar[i][j-1];
        }
        for(int i=l2;i<=r2;i++)
            for(int j=i+1;j<=r2;j++) {
                if(ch[mid][i]!=ch[mid][j]) continue;
                if(ch[mid][i]!=ch[mid+1][i]) continue;
                if(ch[mid][j]!=ch[mid+1][j]) continue;
                L=up[mid][i]>=up[mid][j]?al[i][j]:al[j][i];
                R=dn[mid][i]<=dn[mid][j]?ar[i][j]:ar[j][i];
                ans+=1ll*L*R;
            }
        solve(l1,mid,l2,r2);
        solve(mid+1,r1,l2,r2);
    }
}
int main() {
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            cin>>ch[i][j];
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++) {
            up[i][j]=i>1&&ch[i][j]==ch[i-1][j]?up[i-1][j]:i;
            lef[i][j]=j>1&&ch[i][j]==ch[i][j-1]?lef[i][j-1]:j;
        }
    for(int i=n;i>=1;i--)
        for(int j=m;j>=1;j--) {
            dn[i][j]=i<n&&ch[i][j]==ch[i+1][j]?dn[i+1][j]:i;
            rig[i][j]=j<m&&ch[i][j]==ch[i][j+1]?rig[i][j+1]:j;
        }
    solve(1,n,1,m);
    printf("%lld\n",ans);
}

G. Biological Software Utilities

Find the number of trees with perfect matching \ (n \) points\ (1\le n\le 10^6\).

Solution

Bind two points together. There are \ (n!!=1\times 3\times \ldots \times (n-1) \) methods.
There are \ (\ frac{n}{2})^{n/2-2} \) kinds of trees that can be composed of points tied together.
There are \ (4^{n/2-1} \) kinds of interconnection between points.
Multiply, no, time complexity \ (O(n) \).

Code
const int N=1e6,mod=998244353;
int n;
int ans=1;
int fpow(int x,int y) {
    if(y<0) return 1;
    int ret=1;
    for(;y;y>>=1) {
        if(y&1) ret=1ll*ret*x%mod;
        x=1ll*x*x%mod;
    }
    return ret;
}
int main() {
    scanf("%d",&n);
    if(n%2) {puts("0");return 0;}
    for(int i=1;i<=n;i+=2) ans=1ll*ans*i%mod;
    ans=1ll*ans*fpow(n/2,n/2-2)%mod*fpow(4,n/2-1)%mod;
    printf("%d\n",ans);
}

H. Bytelandia States Union

Go from \ ((x_1,y_1) \) to \ ((x_2,y_2) \) to find the shortest path.
There are different schemes from \ ((x,y) \) to the four directions. See the original topic for details.
\(1\le T\le 5\times 10^4\),\(1\le x_1,y_1,x_2,y_2\le 10^9\).

Solution

Fraud problem, I can responsibly tell you that the cost of a path \ ((x_1,y_1),(x_2,y_2),(x_3,y_3),\ldots,(x_k,y_k) \) is \ (x ^ 2_ky ^ 2_k-x ^ 2_1y ^ 2_1-x_k ^ 2-x_k ^ 2 + \ sum ^ {K} {I = 1} x ^ 2_i + y ^ 2_i \)? Can ask hht2005 , anyway, I won't.
To minimize the path, you only need to minimize the following values, so just get as close to the line \ (x=y \) as possible.
The time complexity of each time is \ (O(1) \).

Code
void solve() {
    int x1,y1,x2,y2;
    scanf("%lld %lld %lld %lld",&x1,&y1,&x2,&y2);
    ans=(p2(1ll*x2*y2%mod)-p2(1ll*x1*y1%mod)+mod)%mod;
    ans=(ans-p2(x2)-p2(y2)+mod)%mod;
    if(x1>x2) swap(x1,x2),swap(y1,y2);
    if(y2>y1)
        if(x1<y1) {
            int nx=min(y1,x2);
            Add(ans,1ll*(nx-x1)*p2(y1)%mod);
            Add(ans,sum(x1,nx-1));
            if(nx==x2) {
                Add(ans,1ll*(y2-y1+1)*p2(x2)%mod);
                Add(ans,sum(y1,y2));
            }
            else {
                int nxt=min(x2,y2);
                Add(ans,(sum(nx,nxt-1)*3ll%mod+sum(nx+1,nxt))%mod);
                if(nxt==y2) {
                    Add(ans,1ll*p2(y2)*(x2-nxt+1)%mod);
                    Add(ans,sum(nxt,x2));
                }
                else {
                    Add(ans,1ll*p2(x2)*(y2-nxt+1)%mod);
                    Add(ans,sum(nxt,y2));
                }
            }
        }
        else {
            int ny=min(x1,y2);
            Add(ans,1ll*(ny-y1)*p2(x1)%mod);
            Add(ans,sum(y1,ny-1));
            if(ny==y2) {
                Add(ans,1ll*(x2-x1+1)*p2(y2)%mod);
                Add(ans,sum(x1,x2));
            }
            else {
                int nxt=min(x2,y2);
                Add(ans,sum(ny,nxt-1)*2ll%mod);
                Add(ans,sum(ny,nxt-1)+sum(ny+1,nxt));
                if(nxt==x2) {
                    Add(ans,1ll*p2(x2)*(y2-nxt+1)%mod);
                    Add(ans,sum(nxt,y2));
                }
                else {
                    Add(ans,1ll*p2(y2)*(x2-nxt+1)%mod);
                    Add(ans,sum(nxt,x2));
                }
            }
        }
    else {
        Add(ans,1ll*(y1-y2)*p2(x1)%mod);
        Add(ans,sum(y2+1,y1));
        Add(ans,1ll*(x2-x1+1)*p2(y2)%mod);
        Add(ans,sum(x1,x2));
    }
    printf("%lld\n",(ans%mod+mod)%mod);
}
signed main() {
    ll t;scanf("%lld",&t);
    while(t--) solve();    
}

I. Binary Supersonic Utahraptors

Alice and Bob are playing games again. Alice has black and white items, and Bob also has black and white items.

There are \ (k \) rounds. In each round, Alice gives Bob \(s_i \) items first, and Bob returns \ (s_i \) items.

Alice wants the difference between Alice's black items and Bob's white items to be as small as possible, while Bob wants to maximize the above items.

Find the last value.

\(1\le n,m,k\le 3\times 10^5\).

Solution

People will be invincible. Alice and Bob can't decide all this.
The answer is the difference between the total number of black items and \ (n \).
Time complexity \ (O(1) \).

Code
#include<bits/stdc++.h>
using namespace std;
int n,m,k,r,y;
int main() {
    scanf("%d %d %d",&n,&m,&k);
    for(int i=1,x;i<=n;i++) {
        scanf("%d",&x);
        if(x==1) r++;
    }
    for(int i=1,x;i<=m;i++) {
        scanf("%d",&x);
        if(x==1) r++;
    }
    printf("%d\n",abs(n-r));
}

J. Burnished Security Updates

Find the smallest independent set covering all edges of a graph, \ (2\le n\le 3\times 10^5 \), \ (1\le m\le 3\times 10^5 \).

Solution

To cover all edges, two adjacent points must have different states.
Considering the coloring of bipartite graphs, if the original graph has odd rings, there must be no solution, otherwise take the smaller point set of that color.
Time complexity \ (O(n+m) \).

Code
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
const int N=3e5;
int n,m,vis[N+10],cnt[4],ans;
vector<int> G[N+10];
bool dfs(int u,int col) {
    vis[u]=col;cnt[col]++;
    bool fl=1;
    for(auto v:G[u])
        if(!vis[v]) fl&=dfs(v,3-col);
        else if(vis[v]==col) return 0;
    return 1;
}
int main() {
    scanf("%d %d",&n,&m);
    for(int i=1,x,y;i<=m;i++) {
        scanf("%d %d",&x,&y);
        G[x].pb(y),G[y].pb(x);
    }
    for(int i=1;i<=n;i++)
        if(!vis[i]) {
            cnt[1]=cnt[2]=0;
            if(!dfs(i,1)) {
                puts("-1");
                return 0;
            }
            ans+=min(cnt[1],cnt[2]);
        }
    printf("%d\n",ans);
}

K. Bookcase Solidity United

There are \ (n \) boards, the \ (I \) board has stability \ (a_i \), and the boards are arranged from high to low.
Place an iridium ball on the board, the \ (I \) board will be broken after being placed with more than or equal to \ (a_i \), and \ (\ lfloor\frac k 2\rfloor \) will fall onto the next board.
Find out at least how many iridium balls are needed to break the front \ (i \) board.
\(1\le n\le 70\),\(1\le a_i\le 150\).

Solution

Let \ (f_{l,r,k} \) represent the minimum number of balls to break the board of \ ([l,r] \) and leave \ (k \) balls.
There is an obvious shift: \ (f {L, R, K} + \ max (a {R + 1} - K, 0) \ to f {L, R + 1, \ max (k, a {R + 1}) / 2} \), which means inheriting several balls to hit the following ones.
At the same time, we consider piecewise smashing, \ (f {L, R, K 1 + K 2} = f {L, mid, K 1} + F {mid + 1, R, K 2} \).
Direct violent transfer is \ (O(n^3m^2) \).

Code
#include<bits/stdc++.h>
using namespace std;
const int N=200,M=200;
int n,a[N+10],m;
int f[N+10][N+10][M+10];
void chkmin(int &x,int y) {
    if(x>y) x=y;
}
int main() {
    scanf("%d",&n);
    memset(f,0x3f,sizeof f);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),f[i][i][a[i]/2]=a[i],m=max(m,a[i]);
    for(int len=2;len<=n;len++)
        for(int l=1;l+len-1<=n;l++) {
            int r=l+len-1;
            for(int i=0;i<=m;i++) chkmin(f[l][r][max(i,a[r])/2],f[l][r-1][i]+max(0,a[r]-i));
            for(int i=0;i<=m;i++)
                for(int j=l;j<r;j++)
                    for(int k=0;k<=i;k++)
                        chkmin(f[l][r][i],f[l][j][k]+f[j+1][r][i-k]);
        }
    for(int i=1;i<=n;i++) {
        int ans=INT_MAX;
        for(int j=0;j<=m;j++) ans=min(ans,f[1][i][j]);
        printf("%d ",ans);
    }
    puts("");
    return 0;
}

M. Brilliant Sequence of Umbrellas

Construct an increasing sequence with a value range of \ ([1,n] \) with a length of at least \ (\ lceil \frac2 3 \sqrt{n}\rceil \), so that the \ (\ gcd \) between two pairs is also increased.
\(1\le n\le 10^{12}\).

Solution

Observe the example, consider constructing a sequence with Coprime every two numbers, and then take the product of two adjacent terms of the sequence as the original sequence.
This must satisfy the \ (\ gcd \) increment.

Code
typedef long long ll;
const int N=1e6;
ll n,a[N+10],cnt,b[N+10];
int main() {
    scanf("%lld",&n);
    b[++cnt]=1,b[++cnt]=1;
    int lim=ceil(2.0*sqrt(n)/3);
    for(ll i=2;cnt<=lim+1&&b[cnt]*i<=n;i++)
        if(__gcd(b[cnt-1],i)==1)
            b[++cnt]=i;
    printf("%lld\n",cnt-1);
    for(int i=1;i<cnt;i++) printf("%lld ",b[i]*b[i+1]);
    puts("");
}

N. Best Solution Unknown

There are \ (n \) individuals playing the game. Everyone has a strength value. The one with a large strength value will defeat the one with a small strength value. All of them have a chance to win.
Winning a person can increase the strength value of \ (1 \), and each person can only play with adjacent people.
Every time you pick a game at random, ask who is likely to win.
\(1\le n\le 10^6\),\(1\le a_i\le 10^9\).

Solution

Consider whether a person can win for a large section, draw the maximum value, and find that the maximum value is divided into two parts, one is left and the other is right. If you want to win the mountain over the maximum value.
Then we can divide and conquer, find the maximum value to divide and conquer, and record at least how much to the left or right each time before we can win.
When divide and conquer, use ST table to speed up the calculation of the maximum value.

Code
const int N=1e6;
int a[N+10],n,Log[N+10],Max[N+10][30],id[N+10][30];
bool nb[N+10];
int query(int l,int r) {
    int k=Log[r-l+1];
    int ret=max(Max[l][k],Max[r-(1<<k)+1][k]);
    if(ret==Max[l][k]) return id[l][k];
    else return id[r-(1<<k)+1][k];
}
void dfs(int l,int r,int c) {
    if(l>r) return;
    if(l==r) {
        if(a[l]>=c) nb[l]=1;
        return;
    }
    int id=query(l,r);
    if(a[id]<c) return;
    nb[id]=1;
    dfs(l,id-1,max(c,a[id]-id+1+l));
    dfs(id+1,r,max(c,a[id]+id+1-r));
}
int main() {
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    Log[1]=0;
    for(int i=2;i<=n;i++) Log[i]=Log[i/2]+1;
    for(int i=1;i<=n;i++) Max[i][0]=a[i],id[i][0]=i;
    for(int j=1;j<=20;j++)
        for(int i=1;i+(1<<(j-1))<=n;i++) {
            Max[i][j]=max(Max[i][j-1],Max[i+(1<<(j-1))][j-1]);
            if(Max[i][j]==Max[i][j-1]) id[i][j]=id[i][j-1];
            else id[i][j]=id[i+(1<<(j-1))][j-1];
        }
    dfs(1,n,0);
    int cnt=0;
    for(int i=1;i<=n;i++) if(nb[i]) cnt++;
    printf("%d\n",cnt);
    for(int i=1;i<=n;i++) if(nb[i]) printf("%d ",i);
    puts("");
}

Posted by blacksnday on Mon, 01 Nov 2021 03:04:56 -0700