test20190815

ゴシップ

この2日間の試験は、ああ、暴力をプレイすると、200ポイントのqwqを持って、本当に素晴らしいです。

フェイス質問

フェイス質問

T1

溶液

それはキューブを差分しているため、キューブは貧しい式とみなすことができます。

\((AB)^ 3 =(A-B)×(^ 2 + \倍B + B ^ 2)\ \)

そしてので\(P \)素数なので、\((AB&)\)\((^ 2 + \回B + B ^ 2)\) 1がなければなりません。明らかに、\は((2 + A ^ \タイムズB + B ^ 2)\) 1、このようにして得られたよりも大きくなければならない(\(AB&))\すなわち、1であり、\(P \)がなければなりません隣接する二つの数字の間キューブ差。

我々は、ときにいくつかのサイクルが、見つけることができる見つけることができる(K = 577351 \)を\場合、\(K ^ 3-(1-K)。3 ^ \)値が最初より大きい\(10 ^ {12} \) だから、直接、最初から、解答または列挙値がより大きい見つけてきました\(P \)最後にすることができます。

時間複雑\(O(N \回MAXK )\)

コード

#include<bits/stdc++.h>
#define del(a,i) memset(a,i,sizeof(a))
#define ll long long
#define inl inline
#define il inl void
#define it inl int
#define ill inl ll
#define re register
#define ri re int
#define rl re ll
#define mid ((l+r)>>1)
#define lowbit(x) (x&(-x))
#define INF 0x3f3f3f3f
using namespace std;
template<class T>il read(T &x){
    int f=1;char k=getchar();x=0;
    for(;k>'9'||k<'0';k=getchar()) if(k=='-') f=-1;
    for(;k>='0'&&k<='9';k=getchar()) x=(x<<3)+(x<<1)+k-'0';
    x*=f;
}
template<class T>il print(T x){
    if(x/10) print(x/10);
    putchar(x%10+'0');
}
ll mul(ll a,ll b,ll mod){long double c=1.;return (a*b-(ll)(c*a*b/mod)*mod)%mod;}
it qpow(int x,int m,int mod){
    int res=1,bas=x%mod;
    while(m){
        if(m&1) res=(res*bas)%mod;
        bas=(bas*bas)%mod,m>>=1;
    }
    return res%mod;
}
const int MAXN = 577351,maxn = 578;
ll T,p;
bool check(ll p){
    for(ri i=1;i<=MAXN;++i){
        rl mns=1ll*i*i*i-1ll*(i-1)*(i-1)*(i-1);
        if(mns==p)
            return true;
        else if(mns>p) return false;
    }
    return false;
}
int main()
{
    freopen("cubicp.in","r",stdin);
    freopen("cubicp.out","w",stdout);
    read(T);
    while(T--){
        read(p);
        if(check(p)) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

T2

溶液

\(70pts \)プラクティス:

以下のための\(60 \)データの%、\(N <= 1000、K <= 20である\)

明らかに\(O(N ^ 2 \回K)\) アルゴリズムをすることによって実行されています。

DPを考えてみましょうこれは、サブジェクト名ではありません

我々は定義\(DP_ {I、Jは} \) の到着を表し\(Iは\)に分割数、\(J \)得られた最小セグメント。

伝達方程式は簡単です。

\(DP_ {I、J} = MIN(DP_ {S、J-1} + val_ {S + 1、I})\)

我々の唯一の前処理\(val_ {I、Jは} \) を直接転送することができます。

私たちは、内部の各ファイルのすべてのポイントがあり、データの範囲を見て\(a_iを\)とまったく同じで。

私たちの簡単な分析、我々は見つけること、私たちはしているとき(k個\)\際に同じ値、\(k個\)も大きく貢献して\(K-1 \)差が大きくなるので、我々はそれをしたいです\(N \)のように分割数平均\(K \)部品。

場合\(Nは\)する(K \)\分割し、各セグメントのサイズは(N / K \)\ ;割り切れない、余分な場合\(REST \)数は、それらに等分します\(休憩\)間隔の。

回答の算出に各セグメント間の良好な寄与、\(ヴァル= \ {FRACサイズ\タイムズ(-size。1)} {2} \)

そして、直接の答えであるの数を乗じました。

コード

#include<bits/stdc++.h>
#define del(a,i) memset(a,i,sizeof(a))
#define ll long long
#define inl inline
#define il inl void
#define it inl int
#define ill inl ll
#define re register
#define ri re int
#define rl re ll
#define mid ((l+r)>>1)
#define lowbit(x) (x&(-x))
#define INF 0x3f3f3f3f
using namespace std;
template<class T>il read(T &x){
    int f=1;char k=getchar();x=0;
    for(;k>'9'||k<'0';k=getchar()) if(k=='-') f=-1;
    for(;k>='0'&&k<='9';k=getchar()) x=(x<<3)+(x<<1)+k-'0';
    x*=f;
}
template<class T>il print(T x){
    if(x/10) print(x/10);
    putchar(x%10+'0');
}
ll mul(ll a,ll b,ll mod){long double c=1.;return (a*b-(ll)(c*a*b/mod)*mod)%mod;}
it qpow(int x,int m,int mod){
    int res=1,bas=x%mod;
    while(m){
        if(m&1) res=(res*bas)%mod;
        bas=(bas*bas)%mod,m>>=1;
    }
    return res%mod;
}
const int MAXN = 1e3+1;
int n,k,a[MAXN],val[MAXN][MAXN],w,dp[21][MAXN],cnt[MAXN][MAXN],last[MAXN];
int main()
{
    freopen("dp.in","r",stdin);
    freopen("dp.out","w",stdout);
    read(n),read(k),del(dp,0x3f);
    if(n<=1000){
        for(ri i=1;i<=n;++i) read(a[i]);
        for(ri i=1;i<=n;++i){
            val[1][i]=val[1][i-1]+cnt[a[i]][last[a[i]]];
            cnt[a[i]][i]=cnt[a[i]][last[a[i]]]+1,last[a[i]]=i;
        }
        for(ri i=2;i<=n;++i){
            ri mns=0;
            for(ri j=i;j<=n;++j){
                if(a[j]==a[i-1]) mns++;
                val[i][j]=val[i-1][j]-mns;
            }
        }
        dp[0][0]=0;
        for(ri s=1;s<=k;++s)
            for(ri i=1;i<=n;++i)
                for(ri j=0;j<i;++j)
                    dp[s][i]=min(dp[s][i],dp[s-1][j]+val[j+1][i]);
        printf("%d",dp[k][n]);
    }
    
    else{
        for(ri i=1;i<=n;++i) read(w);
        ri add=n%k,len=n/k;
        printf("%d",(k-add)*len*(len-1)/2+add*(len+1)*len/2);
    }
    return 0;
}

\(\ 100)は、プラクティスをPTS:

オーダー\(DP_ {I、J} \) 前進を表す\(Iは\)に数\(J \)最小値セグメント。列挙ブレークポイント\(K \)がある(DP_ {I、J} \)\ = \(MIN(DP_ {K、J-sum_ {+}。1. 1 + K、I})\) 実際に、この\(k個の\)は、古典的な1D1D動的プログラミングを使用するように最適化単調です。どのようなああ(霧

コード

#include<iostream>
#include<cstdio>
using namespace std;
const int N=100010;
typedef long long LL;
int c[N],a[N];
LL f[N],g[N];
int p,q,n,k;
LL tot;
void move(int l,int r)
{
    while (l<p) p--,tot+=c[a[p]],c[a[p]]++;
    while (r>q) q++,tot+=c[a[q]],c[a[q]]++;
    while (p<l) c[a[p]]--,tot-=c[a[p]],p++;
    while (r<q) c[a[q]]--,tot-=c[a[q]],q--;
}
void work(int l,int r,int fl,int fr)
{
    if (fl>fr) return;
    int mid=(fl+fr)>>1,mi;
    LL mx=1LL<<60;
    for (int i=l;i<=r;i++)
    if (i<mid)
    {
        move(i+1,mid);
        if (f[i]+tot<mx) mx=f[i]+tot,mi=i;
    }
    g[mid]=mx;
    work(l,mi,fl,mid-1);
    work(mi,r,mid+1,fr);
}
int main()
{
    freopen("dp.in","r",stdin);
    freopen("dp.out","w",stdout);
    scanf("%d%d",&n,&k);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    f[0]=0;
    for (int i=1;i<=n;i++) f[i]=1LL<<60;
    while (k--)
    {
        p=1,q=0,tot=0;
        for (int i=1;i<=n;i++) c[i]=0;
        work(0,n-1,1,n);
        for (int i=0;i<=n;i++) f[i]=g[i],g[i]=0;
    }
    cout<<f[n];
    return 0;
}

T3

溶液

Xの動作のための間隔ペイは、一方のみが矛盾最小のすべてのセクションに起こる:xの範囲を超えて横断面を含む最小値について。

したがって、我々は半分の答えは、すべて最小降順た後、使用やメンテナンスチェックを設定することができます。私は理解できませんでした。

コード

#include <cstdio>
#include <iostream>
#include <algorithm>
#define N 1000011
#define min(x, y) ((x) < (y) ? (x) : (y))
#define max(x, y) ((x) > (y) ? (x) : (y))
using namespace std;
int n, q, ans;
int f[N];

struct node
{
    int x, y, z;
}p[N], t[N];

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
    for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
    return x * f;
}

inline bool cmp(node x, node y)
{
    return x.z > y.z;
}

inline int find(int x)
{
    return x == f[x] ? x : f[x] = find(f[x]);
}

inline bool check(int k)
{
    int i, j, x, y, lmin, lmax, rmin, rmax;
    for(i = 1; i <= n + 1; i++) f[i] = i;
    for(i = 1; i <= k; i++) t[i] = p[i];
    std::sort(t + 1, t + k + 1, cmp);
    lmin = lmax = t[1].x;
    rmin = rmax = t[1].y;
    for(i = 2; i <= k; i++)
    {
        if(t[i].z < t[i - 1].z)
        {
            if(find(lmax) > rmin) return 1;
            for(j = find(lmin); j <= rmax; j++)
                f[find(j)] = find(rmax + 1);
            lmin = lmax = t[i].x;
            rmin = rmax = t[i].y;
        }
        else
        {
            lmin = min(lmin, t[i].x);
            lmax = max(lmax, t[i].x);
            rmin = min(rmin, t[i].y);
            rmax = max(rmax, t[i].y);
            if(lmax > rmin) return 1;
        }
    }
//  cout<<find(1)<<endl;
    if(find(lmax) > rmin) return 1;
    return 0;
}

int main()
{
    freopen("number.in","r",stdin);
    freopen("number.out","w",stdout);
    int i, x, y, mid;
    n = read();
    q = read();
    for(i = 1; i <= q; i++)
        p[i].x = read(), p[i].y = read(), p[i].z = read();
    x = 1, y = q;
    //cout<<check(2)<<endl;
    //return 0;
    while(x <= y)
    {
        mid = (x + y) >> 1;
        if(check(mid)) ans = mid, y = mid - 1;
        else x = mid + 1;
    }
    printf("%d\n", ans);
    return 0;
}

概要

交換が終了した後、ギャングトピック私は彼女がああも、それは理解していなかったものですまだ弱いがわかりました。

または良い燃料ああへ。

おすすめ

転載: www.cnblogs.com/TheShadow/p/11360850.html