Luogu 2-12 recursive recursive bisection

Step problem
n, k Steps can span at most k layers at a time, at least 1 layer. The number of solutions to the nth step
is obvious. The number of solutions to the nth step is the number of solutions to all the previous nk steps. Sum.
If the question requires modulo, then obtain and modulo each time.
Complexity nk, subject data n≤100000, K≤100, can make do

#include<bits/stdc++.h>
using namespace std;
const int MOD=100003;
const int maxn=100005;

int a[maxn]={0};
int main()
{
    int n,k;
    cin>>n>>k;
    a[0]=1;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=k;j++)
        {
            if(i-j<0)break;
            a[i]+=a[i-j];
            a[i]%=MOD;
        }
    }
    cout<<a[n];
}

The division of numbers is
n, k, and the number of solutions (combinations) that divide n into k numbers and add them is
abstracted as a small ball problem:
a total of n small balls are placed in k buckets, what are the ways to put them?
1. There is one ball in at least one bucket;
2. There is more than one ball in each bucket;
the sum of the two cases is all the solutions.
For 1: Then the problem is the same as [put n-1 balls into k-1 buckets] Equivalent
to 2: each bucket does not know a ball, then I take a ball from each bucket, and the sum is added. Just put it back,
then the problem is equivalent to [put nk balls into k buckets]
So we define that a[n][k] is the number of solutions for putting n balls into k buckets,
from small to large You can push it forward.

#include<bits/stdc++.h>
using namespace std;
int n,k,f[201][7]={0};  //f[k][x] k 分成 x 份 ={f[k-1][x-1],f[k-x][x]}
int main()
{
    cin >> n >> k;
    for(int i=1;i<=n;i++)
    {
        f[i][1]=1;
        f[i][0]=1;
    }
    for(int i=2;i<=n;i++)
    {
        for (int x=2;x<=k;x++)
        {
            if (i>x) f[i][x]=f[i-1][x-1]+f[i-x][x];
            else f[i][x]=f[i-1][x-1];
        }
    }
    cout<<f[n][k];
    return 0;
}

In the passing game
, n people make a circle, start the ball in No. 1's hand, and ask the number of solutions that return to No. 1's hand after m passes. The ball can only be given to two adjacent people.
So we define an array a[i][k] to represent the number of schemes for the ith person to get the ball in the kth pass
, [1-n] general a[i][k]=k-1th The number of solutions in the hands of the person with the ball on the left + the person on the right
is: a[i][k]=a[i-1][k-1]+a[i+1][k-1], in 1 and n are dealt with.
We know that the start is in hand number 1, so a[1][0]=1;

#include<bits/stdc++.h>
using namespace std;
const int maxn=33;

int a[maxn][maxn]={0};
int main()
{
    int n,m;
    cin>>n>>m;
    a[1][0]=1;

    for(int k=1;k<=m;k++)
    {
        a[1][k]=a[2][k-1]+a[n][k-1];
        for(int i=2;i<n;i++)
            a[i][k]=a[i-1][k-1]+a[i+1][k-1];
        a[n][k]=a[n-1][k-1]+a[1][k-1];
    }
    cout<<a[1][m];
}

Strange elevator
The elevator on the i-th floor can only go up or down.
There are a total of n floors. From floor A to floor B, the minimum number of elevator rides is required.
Idea: Mark the floors that bfs has been to, do not repeat them

#include<bits/stdc++.h>
using namespace std;

int a[205],vis[205];
int n,A,B;
struct node
{
    int lev,step;
}s,now;
int bfs()
{
    queue<node>q;
    s.lev=A,s.step=0;
    vis[A]=1;
    q.push(s);

    while(!q.empty())
    {
        now=q.front();q.pop();
        if(now.lev==B)
        {
            cout<<now.step;
            return 1;
        }
        int levv=now.lev;
        if(levv+a[levv]<=n)
        {
            s.lev=levv+a[levv];
            s.step=now.step+1;
            if(!vis[s.lev]) 
            {
                vis[s.lev]=1;
                q.push(s);  
            }
        }
        if(levv-a[levv]>=1)
        {
            s.lev=levv-a[levv];
            s.step=now.step+1;
            if(!vis[s.lev]) 
            {
                vis[s.lev]=1;
                q.push(s);  
            }
        }
    }
    return -1;
}
int main()
{
    cin>>n>>A>>B;
    for(int i=1;i<=n;i++) cin>>a[i];
    memset(vis,0,sizeof(vis));
    if(bfs()==-1) cout<<"-1";
}

Number Triangle
Given n and a triangle of n layers, find a path such that the sum is maximal. Each point can only go down left or down right.
Idea: Add the larger number from the bottom to the top, and then recursively

#include<bits/stdc++.h>
using namespace std;
const int maxn=1005;
int a[maxn][maxn]={0};
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=i;j++)
        {
            cin>>a[i][j];
        }
    }
    for(int i=n-1;i>=1;i--)
    {
        for(int j=1;j<=i;j++)
        {
            a[i][j]+=max(a[i+1][j],a[i+1][j+1]);
        }
    }
    cout<<a[1][1];
}

Sequence Segmentation Divide
the sequence into m segments, and find the maximum value of the sum of the smallest segments.
Idea: Dichotomy + Greed

#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
int n,m,a[maxn];
int l,r=0,mid;
inline bool checkk(int x)//将数列分为每段和都<=x
{
    int ans=0,num=0;//ans为该段和,num为段数
    for(int i=1;i<=n;i++)
    {
        if(ans+a[i]<=x) ans+=a[i];
        else ans=a[i],num++;
    }
    return num>=m;//如果段数多于题目要求,就在区间右边继续找
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)//答案必在 max(a[i])与sum(a[i])直接,二分找答案
    {
        cin>>a[i];
        l=max(l,a[i]);
        r+=a[i];
    }
    while(l<=r)
    {
        mid=(l+r)>>1;
        if(checkk(mid))l=mid+1;
        else r=mid-1;
    }
    cout<<l;
    return 0;
}

A bottle cap
is thrown on the ground. In order to simplify the problem, we can consider the A bottle cap to be thrown on a straight line. Now he wants to find B bottle caps from these bottle caps, so that the two closest distances are The biggest, he wanted to know, how much can the biggest be?

Analysis: The problem of maximizing the minimum value -> bisection to find the answer: the two-division interval l=0, r=the distance between the two farthest bottle caps and the
closest two bottle caps is d, then any other two bottle caps that satisfy this method Distance>=A[pos]+d //pos is the last position that satisfies the condition. Our leftmost bottle cap begins to take.

#include<bits/stdc++.h>
using namespace std;
const int maxn=100005;
int n,m,a[maxn];
int l,r,mid;
inline bool checkk(int x)//间距为x
{
    int pos=a[1]+x,num=1;
    for(int i=2;i<=n;i++)
    {
        if(a[i]>=pos)
        {
            pos=a[i]+x;
            num++;
        }
    }
    return num>=m;//如果可取瓶盖数多于题目要求,就在区间右边继续找
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>a[i];
    sort(a+1,a+1+n);
    l=0,r=a[n]-a[1];
    int ans=0;
    while(l<=r)
    {
        mid=(l+r)>>1;
        if(checkk(mid))l=mid+1,ans=max(ans,mid);
        else r=mid-1;
    }
    cout<<ans;
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325687153&siteId=291194637