2019 Multi-University Training Contest 3

时间:2023-01-03 15:14:56

2019 Multi-University Training Contest 3

2019 Multi-University Training Contest 3

 

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int S=8;

ll mult_mod(ll a,ll b,ll c)
{
    a%=c;
    b%=c;
    ll ret=0,tmp=a;
    while (b)
    {
        if (b&1)
        {
            ret+=tmp;
            if (ret>c)
            {
                ret-=c;
            }
        }
        tmp<<=1;
        if (tmp>c) tmp-=c;
        b>>=1;
    }
    return ret;
}

ll pow_mod(ll a,ll n,ll mod)
{
    ll ret=1;
    ll temp=a%mod;
    while (n)
    {
        if(n&1)
        {
            ret=mult_mod(ret,temp,mod);
        }
        temp=mult_mod(temp,temp,mod);
        n>>=1;
    }
    return ret;
}

bool check(ll a,ll n,ll x,ll t)
{
    ll ret=pow_mod(a,x,n);
    ll last=ret;
    for (int i=1; i<=t; i++)
    {
        ret=mult_mod(ret,ret,n);
        if (ret==1&&last!=1&&last!=n-1)
        {
            return 1;
        }
        last=ret;
    }
    if (ret!=1)
    {
        return 1;
    }
    return 0;
}

bool Miller_Rabin(ll n)
{
    if (n<2)
    {
        return 0;
    }
    if (n==2)
    {
        return 1;
    }
    if ((n&1)==0)
    {
        return 0;
    }
    ll x=n-1;
    ll t=0;
    while ((x&1)==0)
    {
        x>>=1;
        t++;
    }
    srand(time(NULL));
    for (int i=0; i<S; i++)
    {
        ll a=rand()%(n-1)+1;
        if (check(a,n,x,t))
        {
            return 0;
        }
    }
    return 1;
}

ll factor[100];
int tol;

ll gcd(ll a,ll b)
{
    if (!b)
    {
        return a;
    }
    return gcd(b,a%b);
}
ll pollard_rho(ll x,ll c)
{
    ll i=1,k=2;
    srand(time(NULL));
    ll x0=rand()%(x-1)+1;
    ll y=x0;
    while (1)
    {
        i++;
        x0=(mult_mod(x0,x0,x)+c)%x;
        ll d=gcd(y-x0,x);
        if (d!=1&&d!=x)
        {
            return d;
        }
        if (y==x0)
        {
            return x;
        }
        if (i==k)
        {
            y=x0;
            k+=k;
        }
    }
}

__int128 quick(__int128 a,__int128 b,__int128 p)
{
    __int128 ret=1%p;
    while (b)
    {
        if (b&1)
        {
            ret=ret*a%p;
        }
        b>>=1;
        a=a*a%p;
    }
    return ret;
}

void findfac(ll n,ll k)
{
    if (n==1)
    {
        return;
    }
    if (Miller_Rabin(n))
    {
        factor[tol++]=n;
        return;
    }
    ll p=n;
    ll c=k;
    while (p>=n)
    {
        p=pollard_rho(p,c--);
    }
    findfac(p,k);
    findfac(n/p,k);
}

__int128 inv(__int128 a,__int128 p){
    return quick(a,p-2,p);
}
int main()
{
    ll t,p,prime;
    __int128 ans;
    scanf("%lld",&t);
    while (t--)
    {
        scanf("%lld",&p);
        for (ll i=p-1; i>=2; i--)
        {
            if (Miller_Rabin(i))
            {
                prime=i;
                break;
            }
        }
        ans=p-1;
        for (__int128 i=p-1;i>prime;i--){
            ans=ans*inv(i,p)%p;
        }
        printf("%lld\n",(ll)ans);
    }
}

  

2019 Multi-University Training Contest 3

2019 Multi-University Training Contest 3

 

#include <bits/stdc++.h>
 
using namespace std;
 
typedef long long ll;
 
const ll N=200010;
 
ll w[N],b[N],n,m;
 
struct node{
    ll num,sum;
}t[N*4];
 
struct data{
    ll num,rk,id;
}a[N];
 
inline void build(ll rt,ll l,ll r) {
    t[rt].num = t[rt].sum = 0;
    if (l == r) {
        return;
    }
    ll mid = (l + r) >> 1;
    build(rt << 1, l, mid);
    build(rt << 1 | 1, mid + 1, r);
}
 
inline void change(ll rt,ll pos,ll l,ll r) {
    if (l == r) {
        t[rt].num = 1;
        t[rt].sum = b[pos];
        return;
    }
    ll mid = (l + r) >> 1;
    if (pos <= mid) {
        change(rt << 1, pos, l, mid);
    } else {
        change(rt << 1 | 1, pos, mid + 1, r);
    }
    t[rt].sum = t[rt << 1].sum + t[rt << 1 | 1].sum;
    t[rt].num = t[rt << 1].num + t[rt << 1 | 1].num;
}
 
inline ll query(ll rt,ll w,ll l,ll r) {
    if (l == r) {
        return t[rt].sum <= w ? t[rt].num : 0;
    }
    ll mid=(l+r)>>1;
    if (t[rt << 1].sum <= w) {
        return t[rt << 1].num + query(rt << 1 | 1, w - t[rt << 1].sum,mid+1,r);
    } else {
        return query(rt << 1, w, l, mid);
    }
}
 
inline bool cmp1(data a,data b) {
    return a.num < b.num;
}
 
inline bool cmp2(data a,data b) {
    return a.id < b.id;
}
 
int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++) {
            scanf("%lld", &w[i]);
            a[i].id = i;
            a[i].num = w[i];
        }
        sort(a + 1, a + n + 1, cmp1);
        for (int i = 1; i <= n; i++) {
            a[i].rk = i;
            b[i] = a[i].num;
        }
        sort(a + 1, a + n + 1, cmp2);
        build(1, 1, n);
        for (int i = 1; i <= n; i++) {
            printf("%lld ", i - query(1, m - w[i], 1, n) - 1);
            change(1, a[i].rk, 1, n);
        }
        printf("\n");
    }
}

  

 

2019 Multi-University Training Contest 3

2019 Multi-University Training Contest 3

 

 

2019 Multi-University Training Contest 3

#include<bits/stdc++.h>

using namespace std;
typedef pair<int,int> PI;
const int maxn=5000;
const int inf=0x3f3f3f3f;
int a[maxn];


struct Min_Cost_Max_Flow{
    struct edge{
        int to,cap,cost,rev;
        edge(){};
        edge(int _to,int _cap,int _cost,int _rev):to(_to),cap(_cap),cost(_cost),rev(_rev){};
    };
    vector<edge>E[maxn];
    int h[maxn],n,d[maxn],preV[maxn],preE[maxn];
    void init(int n){
        this->n=n;
        for (int i=0;i<=n;i++){
            E[i].clear();
            h[i]=0;
        }
    }
    void add(int from,int to,int cap,int cost){
        E[from].push_back(edge(to,cap,cost,E[to].size()));
        E[to].push_back(edge(from,0,-cost,E[from].size()-1));
    }

    PI dijkstra(int s,int t,int f){
        int cost=0,flow=0;
        for (int i=0;i<=n;i++){
            h[i]=0;
        }
        while (f){
            priority_queue<PI,vector<PI>,greater<PI> >q;
            for (int i=0;i<=n;i++){
                d[i]=inf;
            }
            d[s]=0;
            q.push(make_pair(0,s));
            while (!q.empty()){
                PI now=q.top();
                q.pop();
                int v=now.second;
                if (d[v]<now.first){
                    continue;
                }
                for (int i=0;i<E[v].size();i++){
                    edge &e=E[v][i];
                    if (e.cap>0&&d[e.to]>d[v]+e.cost+h[v]-h[e.to]){
                        d[e.to]=d[v]+e.cost+h[v]-h[e.to];
                        preV[e.to]=v;
                        preE[e.to]=i;
                        q.push(make_pair(d[e.to],e.to));
                    }
                }
            }
            if (d[t]==inf)break;
            for (int i=0;i<=n;i++){
                h[i]+=d[i];
            }
            int d=f;
            for (int i=t;i!=s;i=preV[i]){
                d=min(d,E[preV[i]][preE[i]].cap);
            }
            f-=d;
            flow+=d;
            cost+=d*h[t];
            for (int i=t;i!=s;i=preV[i]){
                    edge &e=E[preV[i]][preE[i]];
                    e.cap-=d;
                    E[i][e.rev].cap+=d;
            }
        }
        return make_pair(flow,cost);
    }
}G;

int main() {
    int t,k,n;
    scanf("%d", &t);
    while (t--) {
        scanf("%d%d", &n, &k);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
        }
        G.init(2*n+2);
        int S = 0, T = 2 * n + 2;
        G.add(S, n * 2 + 1, k, 0);
        for (int i = 1; i <= n; i++) {
            G.add(n * 2 + 1, i, 1, 0);
            G.add(i, n + i, 1, -a[i]);
            G.add(n + i, T, 1, 0);
        }
        for (int i = 1; i <= n; i++) {
            for (int j = i + 1; j <= n; j++) {
                if (a[i] <= a[j]) {
                    G.add(n + i, j, 1, 0);
                }
            }
        }
        PI ans=G.dijkstra(S,T,inf);
        printf("%d\n",-ans.second);
    }
}

  

 

2019 Multi-University Training Contest 3

2019 Multi-University Training Contest 3

 

 

 

2019 Multi-University Training Contest 32019 Multi-University Training Contest 3

 

题意:要求把一个序列分成连续的k块(可以去掉后缀),使得权值和最大的那一块权值最小,求出这个最小值

解法:二分这个权值,然后根据权值去把序列切块,如果能切成k块甚至更多,那么一定合法,否则不合法,怎么check呢?设d[i]为前 i 个数在最大权值限制在T时最多能切的块数,转移:对于所有的 L < i,如果sum[i] - sum[L] <= T,那么d[i] = max(d[i], d[L] + 1),很显然这个dp check复杂度是n^2,我们变形:sum[i] - T <= sum[L],我们二分找到最小的sum[L],然后在线段树中查其区间[sum[L], max(sum[x])]最大值mx,d[i] = mx + 1即可,然后在线段树的 sum[i]点更新d[i]。