牛客小白月赛75

A.直接比较y和z的最小值即可

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
#include 
#include
using namespace std;
const int N = 2e5+10,mod=1e9+7;
#define int long long
int n,m;
int a[N];

void solve()
{
    int x,y,z;
    cin>>x>>y>>z;
    cout<>t;
    while(t--) solve();
}

B 最大化直接让得3分全在前面即可

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
#include 
#include
using namespace std;
const int N = 2e5+10,mod=1e9+7;
#define int long long
int n,m;
int a[N];

void solve()
{
    int x,y;
    cin>>n>>x>>y;
    for(int i=1;i<=n;i++) cin>>a[i];
    int res=0;
    sort(a+1,a+1+n,greater<>());
    for(int i=1;i<=n;i++){
        if(a[i]>y) res+=3;
    }
    cout<>t;
    while(t--) solve();
}

C.递归我写的比较复杂就不贴了

D

直接跑最短路模板

状态只有n*m个点,每个点要么不改变当前值,要么改变当前值

所以状态只有n*m*2个不同状态

然后直接跑个dijkstra模板即可

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
#include 
#include
using namespace std;
const int N = 1010,mod=1e9+7;
typedef pair PII;
using node=tuple;
int n,m;
char a[N][N];
int dist[N][N][2];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};

void bfs(){
    priority_queue,greater> q;
    q.emplace(0,0,1,1);
    memset(dist,-1,sizeof(dist));
    int res=0x3f3f3f3f;
    while(q.size())
    {
        auto [d,s,x,y]=q.top();
        q.pop();
        if(dist[x][y][s]!=-1) continue;
        dist[x][y][s]=d;
        if(x==n&&y==m) res=min(res,d);
        for(int i=0;i<4;i++)
        {
            int tx=x+dx[i],ty=y+dy[i];
            if(tx<=0||ty<=0||tx>n||ty>m) continue;
            int t=a[x][y]-'0';
            if(s==1)
            {
                t=t^1;    
            }
            if(t!=a[tx][ty]-'0')
            {
                q.emplace(d+1,0,tx,ty);
            }
            else{
                q.emplace(d+2,1,tx,ty);
            }
        }
    }
    cout<>n>>m;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++)
            cin>>a[i][j];
    }
    bfs();
}

signed main(){
    cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
    int t=1;
   // cin>>t;
    while(t--) solve();
}

E.

额考虑dp

前i个数,当前倍数是第i-1个总和得j倍

首先初始化1,任何数都可以

假设当前数i,当前数得总和能是i*j,那么因为第i个数能去取到1到m

即最小值是i*j-m,最大值是i*j-1

那么能取到i-1个数总和的x倍数

可以发现这是一个连续的区间

用树状数组优化即可

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
#include 
#include
using namespace std;
const int N = 2010,M=2010*2010,mod=1e9+7;
#define int long long
typedef pair PII;
using node=tuple;
int tr[M];
int n,m;
int f[N][N];
int lowbit(int x)
{
    return x & -x;
}

void add(int x, int c)  // 位置x加c
{
    for (int i = x; i < M; i += lowbit(i)) tr[i] += c,tr[i]=(tr[i]%mod+mod)%mod;
}

int sum(int x)  // 返回前x个数的和
{
    if(x<=0) return 0;
    int res = 0;
    for (int i = x; i; i -= lowbit(i)) res += tr[i],res=(res%mod+mod)%mod;
    return res;
}

void solve()
{
    cin>>n>>m;
    for(int i=1;i<=1;i++)
    {
        for(int j=1;j<=m;j++)
        {
            f[i][j]=1;
            add(j,1);
        }
    }
    for(int i=2;i<=n;i++){
        for(int j=1;j<=m;j++){
            int l=(i*j-m+(i-1-1))/(i-1);
            int r=(i*j-1)/(i-1);
            if(l<=0) l=1;
            f[i][j]=((sum(r)-sum(l-1))%mod+mod)%mod;
        }
        for(int j=1;j<=m;j++)
        add(j,-f[i-1][j]+f[i][j]);
    }
    cout<<(sum(m)%mod+mod)%mod;
}

signed main(){
    cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
    int t=1;
   // cin>>t;
    while(t--) solve();
}

F .不会0.0

你可能感兴趣的:(算法)