AtCoderグランドコンテスト問題の解決019

ポータル

\(\)

コキュ

int a,b,c,d,n,t;
int main(){
    scanf("%d%d%d%d%d",&a,&b,&c,&d,&n);
    t=n&1,n-=t,a*=8,b*=4,c*=2;
    printf("%lld\n",1ll*min(min(a,b),min(c,d))*(n>>1)+(min(min(a,b),c)>>1)*t);
    return 0;
}

\(Bの\)

同じ演算結果を考慮していない、その場合、ロールオーバー間隔見出さ\([L、R] \ ) を満たす(S [L] = sで\ \ [R])をその後、我々はできるようになりました選択操作\([L + 1 、R-1] \)最終シーケンスと反転するように\([L、R]が\ ) 以下の配列と同じである、我々はカウントしない([L、R] \ \ ) ので、我々は唯一の数を数えます以下のための\([L、R] \ ) を満足\(S [L] \\ NEQ S [R&LT] \) 最終的な回答\(1 + \)

typedef long long ll;
const int N=2e5+5;
char s[N];int cnt[26],n,sum;ll res;
int main(){
    scanf("%s",s+1),n=strlen(s+1);
    fp(i,1,n)res+=sum-cnt[s[i]-'a'],++cnt[s[i]-'a'],++sum;
    printf("%lld\n",res+1);
    return 0;
}

\(C \)

直接マトリックスに指摘し、その後にするために、小から大まで縦軸を押す(X \)\長場合、立ち上がりシーケンスを構成する\(K <分(X_2 - X_1、Y_2 - Y_1)+ 1 \) あなたはコーナーができ(K \)\、時間を短縮\((20-5 \ PI)のk \)を

それ以外の場合は、唯一のコーナー\(K-1 \)回、その後減少、半円を歩く\((20-5 \パイ)( K-1)\) プラス\((10 \パイ-20) \)

//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int N=2e5+5;const double Pi=acos(-1.0);
int x[N],y[N],id[N],f[N],num[N];
int n,tot,cnt;
inline bool cmp(const int &a,const int &b){return y[a]<y[b];}
int main(){
    int x1,y1,x2,y2;
    scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&n);
    fp(i,1,n)scanf("%d%d",&x[i],&y[i]);
    if(x1>x2)swap(x1,x2),swap(y1,y2);
    if(y1>y2){
        swap(y1,y2);
        fp(i,1,n)y[i]=y1+y2-y[i];
    }
    fp(i,1,n)id[i]=i;
    sort(id+1,id+1+n,cmp);
    fp(i,1,n){
        R int u=id[i];
        if(y[u]>=y1&&y[u]<=y2&&x[u]>=x1&&x[u]<=x2)
            num[++tot]=x[u];
    }
    cnt=0,f[cnt]=-1;
    fp(i,1,tot){
        if(num[i]>f[cnt])f[++cnt]=num[i];
        else{
            R int k=lower_bound(f+1,f+1+cnt,num[i])-f;
            f[k]=num[i];
        }
    }
    R double res;
    if(cnt<min(x2-x1,y2-y1)+1)
        res=100.0*(x2-x1+y2-y1)-(20-Pi*5)*cnt;
    else res=100.0*(x2-x1+y2-y1)-(20-Pi*5)*(cnt-1)+(10*Pi-20);
    printf("%.12lf\n",res);
    return 0;
}

\(D \)

第列挙\(A \)という最終位置と(B_1 \)\一致し、各位置および範囲の最終位置は、それがプロセスに遭遇するか否かを判断ならば\(1 \) yesの場合、それはどこになることができます

そうでなければ、我々は左に到達することはできません追加の各ポイントを見つける\(/ \)あなたが左に遠いを行くために左に行った場合、最小距離の右の動き、そして残りはまた遠い左それ以外の場合は、左に行くことができますあなたは右に行かなければなりません。同様にこれまでと同じである回

全体的に複雑\(O(N ^ 2 \ログN)\)

//quming
#include<bits/stdc++.h>
#define R register
#define fi first
#define se second
#define pb emplace_back
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
typedef pair<int,int> pi;
const int N=2005,inf=0x3f3f3f3f;
char s[N*3],s1[N];
int sum[N*3],nl[N*3],nr[N*3],res,len;
vector<pi>vc;
void init(){
    nl[0]=-inf;
    fp(i,1,len*3)nl[i]=(s[i]=='1'?i:nl[i-1]);
    nr[len*3+1]=inf;
    fd(i,len*3,1)nr[i]=(s[i]=='1'?i:nr[i+1]);
    fp(i,1,len*3)sum[i]=sum[i-1]+(s[i]=='1');
}
inline int findl(R int x){return min(inf,x-nl[x]);}
inline int findr(R int x){return min(inf,nr[x]-x);}
int main(){
    scanf("%s%s",s1+1,s+1),res=inf;
    len=strlen(s+1);
    fp(i,len+1,len*3)s[i]=s[i-len];
    init();
    fp(i,1,len*2+1){
        vc.clear();
        R int c=0;
        fp(j,1,len)if(s1[j]!=s[i+j-1]){
            ++c;
            R int r=j+len,l=j+i-1;
            if(l>r)swap(l,r);
            if(sum[r]-sum[l-1]==0)
            vc.pb(pi(findl(l),findr(r)));
        }
        vc.pb(pi(0,0));
        sort(vc.begin(),vc.end());
        reverse(vc.begin(),vc.end());
        R int tmp=inf,mx=0;
        for(auto p:vc){
            if(p.fi!=inf&&mx!=inf)cmin(tmp,mx*2+p.fi*2);
            cmax(mx,p.se);
            if(mx==inf)break;
        }
        if(tmp!=inf)cmin(res,tmp+abs(len+1-i)+c);
    }
    if(res==inf)res=-1;
    printf("%d\n",res);
    return 0;
}

\(E \)

仙は何ああ、これらの方法を考える......

有用な第一の位置の2つだけ、2つの完全な\(1 \)または\(1 \)\(0 \) フルコンビニエンス\(1 \)は、中間点で示さ\(1 \)を\(0 \)は、左の点、表記\(0 \)\(1 \)右のポイントを行うための心の中を。呼ばれる中間点の数\(A \) 左と右の点の数は点である\(B \)

私たちの最初の試合、その後はのために、順序を考える(a_iを、b_i)\(\ ) が一致、\(a_iを\)をする(b_i \)\ 1つの側に接続されているが、最終的な描画がリングプラスチェーンのいくつかの部分の数は確かにあります、リングは中間点で、開始点と終了点の周りの鎖は、それぞれ、中間体は、中間点です。チェーンに固定されるリング、操作の上記配列のいずれか、動作のシーケンス

SOL1

セット([I]、[J F \ ] \) を表し\(J \)への中間点\を(私は\)プログラムチェーンの数、\([I] [J F ] = \和_ {Kの\のGEQ 0} {F [I-1] [JK] \上(K + 1)!} \) 分母は鎖表す\(K + 1 \)の固定エッジのシーケンスを、最終的な答えであります\(!のB!(A + B)!\ sum_ {I = 0} ^ A F [B] [I] \) \((A + B)は! \) 容易に配置エッジを表し、(\ !\)\(B!\)表す2つの基準点の間に存在

我々多項式を乗じた各転送等価\(\ sum_ {私はGEQ 0 \} {1 \ Iは、+(上1)!} X ^ I \) ライン上の次に多項式急速パワーの複雑\(O )\(N Nを記録\)

SOL2

別の方法が提供される([I]、[J F \ ] \) 総プット表す\(Iは\)の中間点と\(J \)を、左点目

\ [\開始{整列} F [I] [J] = iが\回Jの\回F [I-1]〜[J] + F J ^ 2 \回[I]、[J-1] \端{整列} \]

フロント挿入は、任意の参照番号は、すなわち、容易に交換することができるので、前標識することによって、その中間点である\(Iは\) その後、いずれか、チェーンの後ろに挿入することができるようにすることにより、\(J \)

後者は、新しい左のポイントを挿入するので、任意の共感ラベル取ることです\(j個\)を、そしてあなたがでそう、右の点のいずれかを選択することができますので、\(jは\)

複雑\(O(N ^ 2) \) すでに渡さ

しかし、それはまた、多項式最適化、設計のかもしれ\(G [i]の[J] = {F [I] [J] \オーバー(J!)^ 2(I!)} \) そこ\(G [i]が[J] = G [I] [J-1] + J \回数G [I-1]〜[J] \)

オリジナルは、左から開始乗じたそれぞれの上にダウンする右下のグリッドとして表示することができます\(IJ \)すぐに乗って、\(J ^ 2 \) 全てのパスの重みと求めます\(G [i]の[J ] \) だけが後になりますダウンする\(jは\)

その後、我々は最初の列挙(私は\)\をカラムはいくつかの手順を取った、最初の発見(私は\)\を列を生成することである({1 \オーバー1-IX} \)\、答えは生成関数のすべての列であります製品、直接パーティション\(NTT + \)逆複雑に多項式\(O(N ^ログ\ \)2 N)を

その怠惰なだけで書くので\(O(N ^ 2) \) の

//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int P=998244353;
inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;}
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
    R int res=1;
    for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
    return res;
}
const int N=10005;
char s[N],t[N];int fac[N],ifac[N],f[N][N],n,cnta,cntb;
inline int C(R int n,R int m){return m>n?0:1ll*fac[n]*ifac[m]%P*ifac[n-m]%P;}
inline void init(int n=10000){
    fac[0]=ifac[0]=1;fp(i,1,n)fac[i]=mul(fac[i-1],i);
    ifac[n]=ksm(fac[n],P-2);fd(i,n-1,1)ifac[i]=mul(ifac[i+1],i+1);
}
int main(){
    init();
    scanf("%s%s",s+1,t+1),n=strlen(s+1);
    fp(i,1,n){
        cnta+=(s[i]=='1'&&t[i]=='1');
        cntb+=(s[i]=='1'&&t[i]=='0');
    }
    f[0][0]=1;
    fp(j,1,cntb)f[0][j]=mul(fac[j],fac[j]);
    fp(i,1,cnta)fp(j,1,cntb)
        f[i][j]=(1ll*i*j%P*f[i-1][j]+1ll*j*j%P*f[i][j-1])%P;
    R int res=0;
    fp(i,0,cnta){
        R int j=cnta-i;
        upd(res,1ll*f[i][cntb]*fac[j]%P*fac[j]%P*C(cnta,j)%P*C(cnta+cntb,j)%P);
    }
    printf("%d\n",res);
    return 0;
}

\(F \)

良好なS ......

まず、そこに残っていることを前提としてい\(N \)\(\はい)\(m個\)\(ノー\) そして答えは確かに、より多くのを選択しているのと同じものであれば、単にマスク

その後、我々はからそしてある答えがスキームに相当し、座標系にこの事を置く\((N、M)\ ) の出発\((0,0)\) もし\(Y = X \ )この行は寄与は上記に下がるだろう、寄与以下左に行く、二つの部分に座標系

想定\(N-M = \) およびプロセスが遭遇した対角行かない、関係なく散歩の貢献の上または下に行くされない\(N \)

それ以外の場合は、仮定\(N- \のGEQのm個\) そして我々は、最初に左に行くだろう、対角線の前に行く\(NM \)ステップを、斜めの場合、私たちはそれぞれの対角線に会いましたいくつかの部分に分割パス円は、各部分の寄与が寄与の対角線に遭遇しなかったの前に言われて、合計寄与がなければならない(N- \)\場合、同じように\(M \のGEQのN \)貢献がなければならないとき\(m個\)

次に対角線上の点は、関係なく、方法のすべての寄与有効にする\({2上1 \}を\) 我々はそれができる確率が何であるかを各点を通過するかを決定します

//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int P=998244353;
inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;}
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
    R int res=1;
    for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
    return res;
}
const int N=1e6+5;
int fac[N],ifac[N],n,m,res;
inline int C(R int n,R int m){return m>n?0:1ll*fac[n]*ifac[m]%P*ifac[n-m]%P;}
inline int calc(R int n,R int m){return C(n+m,n);}
inline void init(int n=1e6){
    fac[0]=ifac[0]=1;fp(i,1,n)fac[i]=mul(fac[i-1],i);
    ifac[n]=ksm(fac[n],P-2);fd(i,n-1,1)ifac[i]=mul(ifac[i+1],i+1);
}
int main(){
    init();
    scanf("%d%d",&n,&m);
    fp(i,1,min(n,m))upd(res,mul(calc(i,i),calc(n-i,m-i)));
    res=mul(res,ksm(mul(calc(n,m),2),P-2));
    upd(res,max(n,m));
    printf("%d\n",res);
    return 0;
}

おすすめ

転載: www.cnblogs.com/yuanquming/p/11600267.html
おすすめ