BZOJ4625 [BJOI2016]最小カット水晶

問題の意味の説明

あなたは、三次元座標系を与え、座標系\((X_I + Y_I + z_i )\ BMOD 3 = 0 \) サイト内のエネルギー源を有します。所与の(\ N-)\エネルギー値を含む点\(C_I \)結晶を、電源が結晶上に位置する場合、結晶は、エネルギー値増加する(\ 10 \%を\)

水晶共振ケースの二種類、1〜3個の隣接する水晶振動子は、第二は、2つの結晶の長さとしてあり、ある\(2 \)線分、線分の中点とエネルギー源の両端。

あなたは、結晶の一部、ウィルない結晶共振後に残った最大のエネルギー値を爆破することができます。

練習

以下のための\((X_I + Y_I + z_i \)3 \ BMODない= 0 \) 黒と白の汚れ点、エネルギー源の周りに黒または白のドットが存在する場合には、図に示す共振器を、そこに構成しなければなりません。

1.png

だから我々は置くことができます\(\ BMOD 3 \)の各分岐点の意味での点の3種類。明らかに、最小コストの損傷、最小カットモデルを使用し、各共鳴のために、考えてみましょう。スプリットポイントの各ポイント、結晶エネルギー値の右側\(C_I \) その後、ソース接続\(1 \)ポイント\(1 \)が接続された\(0 \)、\ (0 \)接続\(2 \)、\ (2 \)接続された合流点、合計結晶に対する答えをエネルギー\(\和C_Iの\は)最大流量を保存します。ここでは、コードの実装は以下のとおりです。

const int inf=1e9;
inline void link(int a,int b,int c)
{
    add_edge(S,a<<1,inf);add_edge(a<<1|1,b<<1,inf);
    add_edge(b<<1|1,c<<1,inf);add_edge(c<<1|1,T,inf);
}

我々は、次に、各点を表すための構造を使用し\((X_I、Y_I、z_iは )\) に変換される((X_I-z_i、Y_I-z_i)\)\、重隔離のベクトル構造をアップロード>+で、オペレーターを予算mapのベクトルを操作するために、問題は終わりました。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register int
#define db double
#define ak *
#define in inline
in char getch()
{
    static char buf[1<<12],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<!2,stdin),p1==p2)?EOF:*p1++;
}
char qwq;
#define gc() getch()
in ll read(re p=0)
{
    ll cz=0,ioi=1;qwq=gc();
    while(qwq<'0'||qwq>'9') ioi=qwq=='-'?~ioi+1:1,qwq=gc();
    while(qwq>='0'&&qwq<='9') 
    {
        cz=(cz<<3)+(cz<<1)+(qwq^48),qwq=gc();
        if(p) cz%=p;
    }
    return cz ak ioi;
}
const int p=998244353;
ll ans;
ll n,tot,m,k,inv[20000005],prime[5000005],vis[20000005],a[20000005],b[20000005];
inline ll qpow(ll x,ll y,ll z=1)
{
    x%=p;
    for(;y;y>>=1,x=(x*x)%p) z=(y&1)?(z*x)%p:z;
    return z;
}
inline ll get_inv(ll x) {return qpow(x,p-2);}
inline void get_sum(re len)
{
    a[1]=1;
    for(re i=2;i<=len;i++)
    {
        if(!vis[i]) prime[++prime[0]]=i,a[i]=qpow(i,k);
        for(re j=1;j<=prime[0];j++)
        {
            if(i*prime[j]>len) break;
            vis[i*prime[j]]=1;a[i*prime[j]]=a[i]*a[prime[j]]%p;
            if(i%prime[j]==0) break;
        }
    }
}
in ll lagrange(ll n)
{
    if(n<=tot) return b[n];
    ll nw=0,tmp=1;a[tot+1]=1;
    for(re i=tot;i;i--) a[i]=a[i+1]*(n-i)%p;
    for(re i=1;i<=tot;i++)
    {
        ll t=a[i+1]*inv[i-1]%p*inv[tot-i]%p;
        ll res=((tot-i)&1)?-1:1;
        ans=(ans+1ll*b[i]*tmp%p*t%p*res%p)%p;
        tmp=tmp*(n-i)%p;
    }
    return ans;
}
int main()
{
    n=read(p);k=read();tot=k+3;
    inv[0]=inv[1]=1;
    for(re i=2;i<=tot;i++) inv[i]=(ll)(p-p/i)*inv[p%i]%p;
    for(re i=2;i<=tot;i++) inv[i]=inv[i]*inv[i-1]%p;
    if(k==1) return printf("%lld",(n-1)*(n+1)%p),0;
    if(n<=1e5)
    {
        get_sum(n+n-1);
        for(re i=2;i<=n+n-1;i++)
        {
            ll t=(n-abs(n+1-i))/2;
            cout<<a[i]<<" ";
            ans+=a[i]*t%p;ans=(ans%p+p)%p;
        }
    }
    else
    {
        get_sum(tot*2+1);
        for(re i=1;i<=tot<<1;i++) a[i]=(a[i]+a[i-1])%p;
        for(re i=1;i<=tot;i++) b[i]=((b[i-1]+a[2*i-1])%p-a[i])%p;
        ans=(lagrange(n)%p+p)%p;
    }
    printf("%lld\n",ans*(n-1)%p*get_inv(1ll*n*(n-1)/2)%p);
}

おすすめ

転載: www.cnblogs.com/disangan233/p/11140147.html