プレスレビューのようなDPのトピック

プレスレビューのようなDPのトピック

(いくつかの水問題は、あまりにも、私はジャンプを指示します)

スキルの概要:

1.選択された行の圧力行列\(N * 2 ^ N \ )

D [BZOJ2734] [HNOI2012]数字のセットから選択

若は十分ではなかった、私はこれがより難しい質問だと思うので、私は長い時間のためにこだわっています

図から分かるように、すべての数が互いに直接的な影響との間に構成する\(DAG \) エッジがある\(I-iは、2 *> I->はiが3 \の*)

各通信ブロックを除去した後の独立したセット番号であります

\(DAG \)も独立したセットを命ずることができますか?

実際には、我々は驚くべき発見を得ることができ、この\(DAG \)は、あまりにもきちんとされていることである、トレリスは、隣接する点のトレリスが問題を取ることができないです

この、格子状の圧力


const int N=1e5+10,P=1e9+1;
 
 
 
int n;
ll dp[20][1<<11];
int A[20];
 
ll Solve(int i){ 
    int t=0;
    A[0]=0;
    dp[0][0]=1;
    for(;i<=n;i*=2) {//网格图的列数
        t++;
        A[t]=0;
        int c=0;
        for(int j=i;j<=n;j*=3) A[t]|=1<<(c++); //取出网格图这一行的大小
        rep(j,0,A[t]) dp[t][j]=0;
        rep(S1,0,A[t-1]) {
            int fl=1;
            rep(j,0,c+1) if((S1&(1<<j)) && (S1&(1<<(j+1)))) fl=0;
            if(!fl) continue;
            int R=A[t]^(S1&A[t]);
            for(reg int S2=R;;S2=(S2-1)&R) {
                int fl=1;
                rep(j,0,c-1) if((S2&(1<<j)) && (S2&(1<<(j+1)))) fl=0;
                if(!fl) {
                    if(!S2) break;
                    continue;
                }
                (dp[t][S2]+=dp[t-1][S1])%=P;
                if(!S2) break;
            }
        }
    }
    ll res=0;
    rep(i,0,A[t]) res+=dp[t][i];
    res%=P;
    return res;
}
 
 
 
int main(){
    n=rd();
    ll ans=1;
    rep(i,1,n) {
        if(i%2==0||i%3==0) continue;
        //这是一个联通块
        ans=ans*Solve(i)%P;
    }
    printf("%lld\n",ans);
}
 

\ [\ \]

\ [\ \]

G [BZOJ1097] [POI2007]観光スポットATR

フロントポイントとTSPの間のk個のDISの前処理は同じであるが、限定され

int d[30][30];
#include<bits/stdc++.h>
using namespace std;
 
#define reg register
//typedef long long ll;
typedef int ll;
#define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)
 
char IO;
 
int rd(){
    int s=0,f=0;
    while(!isdigit(IO=getchar())) if(IO=='-') f=1;
    do s=(s<<1)+(s<<3)+(IO^'0');
    while(isdigit(IO=getchar()));
    return f?-s:s;
}
 
const int N=20010,M=2e5+10;
 
#pragma GCC optimize(3)
#pragma GCC optimize(2)
#define chk(a,b) ((a>b)&&(a=b))
 
int n,m,k;
 
 
ll dis[N];
 
struct Node{ 
    int x;
    ll d;
    int operator < (const Node __) const{
        return x<__.x;
    }
};
vector <Node> G[N];
 
 
int s[N<<2];
 
int pos[N];
 
 
inline void push(reg int x) {
    int p=pos[x];
    while(p>1) {
        p>>=1;
        if(dis[s[p<<1]]<dis[s[p<<1|1]]) s[p]=s[p<<1];
        else s[p]=s[p<<1|1];
    }
}
 
inline int top(){
    reg int x=s[1];
    s[pos[x]]=0;
    push(x);
    return x;
}
 
void Build(int p,int l,int r) {
    if(l==r) {
        pos[l]=p;
        return;
    }
    reg int mid=(l+r)>>1;
    Build(p<<1,l,mid);
    Build(p<<1|1,mid+1,r);
}
//用线段树实现堆的功能
 
void GetDis(int st,int R) {
    memset(dis,63,sizeof dis); dis[st]=0;
    for(reg int i=1;i<=n;++i) s[pos[i]]=i;
    push(st);
    int cnt=0;
    while(dis[s[1]]<=1e9) {
        reg int u=top();
        if(u<=R && (++cnt>=R) ) return;
        rep(i,0,G[u].size()-1) {
            int v=G[u][i].x,w=G[u][i].d;
            if(dis[v]<=dis[u]+w) continue;
            dis[v]=dis[u]+w;
            push(v);
        }
    }
}
 
int fa[35];
int dp[1<<20][22];
int Log[1<<21];
 
int tmp[35];
 
int main(){
    n=rd(),m=rd();
    k=rd()+1;
    rep(i,0,21) Log[1<<i]=i;
    rep(i,1,m) {
        int u=rd(),v=rd(),w=rd();
        G[u].push_back((Node){v,w});
        G[v].push_back((Node){u,w});
    }
    int q=rd();
    rep(i,1,q) {
        int u=rd(),v=rd();
        fa[v]|=1<<(u-2);
    }
    Build(1,1,n);
    rep(i,1,k) {
        GetDis(i,k);
        rep(j,1,k) d[i][j]=dis[j];
    }
    GetDis(n,n);
    int A=(1<<(k-1))-1;
    memset(dp,63,sizeof dp);
    dp[0][1]=0;
    for(reg int S=0;S<A;++S) {
        reg int T=S;
        int cnt=0;
        rep(j,0,k-2) if(~S&(1<<j)) if((fa[j+2]&S)==fa[j+2]) tmp[++cnt]=j+2;
        while(T) {
            reg int i=Log[T&-T]+2;
            T&=T-1;
            if(dp[S][i]>1e9) continue;
            rep(k,1,cnt) {
                int j=tmp[k];
                reg int NS=S|(1<<(j-2));
                chk(dp[NS][j],dp[S][i]+d[i][j]);
            }
        }
        do {
            reg int i=1;
            if(dp[S][i]>1e9) continue;
            rep(k,1,cnt) {
                int j=tmp[k];
                reg int NS=S|(1<<(j-2));
                chk(dp[NS][j],dp[S][i]+d[i][j]);
            }
        } while(0);
    }
    ll ans=1e9;
    rep(i,1,k) ans=min(ans,dp[A][i]+dis[i]);
    printf("%d\n",ans);
}
 

\ [\ \]

\ [\ \]

H [BZOJ2004] [Hnoi2010]バスBUS線

\(N \)されている\(10 ^ 9 \) マトリックスは、それはないですか?

\(DP [S] \)表現の前に\(のp \)車を置くためにポイントサイトが、どうやら状態保証\(POPCOUNT(S)== k個 \)

状態は、その後、実際に最もされているので、\は(C_ {10} ^ { 5} = 252 \) マトリックスを実行することができます

 
bool be;
 
int n,p,k;
 
int dp[1<<10];
int cnt[1<<10];
int tmp[1<<10];
int A;
 
 
int st[300],sc,id[1<<10];
int f[1][300],ans[1][300];
 
 
int B;
 
 
struct Mat{
    int a[300][300];
    void init(){ memset(a,0,sizeof a); }
    void Get1(){ rep(i,1,sc) a[i][i]=1; }
    Mat operator * (const Mat x) const {
        Mat res;
        for(reg int i=1;i<=sc;++i) {
            for(reg int j=1;j<=sc;++j) {
                ll t=0;
                for(reg int o=1;o<=sc;++o) t+=a[i][o]*x.a[o][j];
                res.a[i][j]=t%P;
            }
        }
        return res;
    }
}res,x;
 
 
 
 
void Solve(){
    A=(1<<p)-1;
    rep(i,1,A) cnt[i]=cnt[i&(i-1)]+1;
    rep(S,0,A) if(cnt[S]==k) ++sc,id[st[sc]=S]=sc;
    rep(S,0,A) if(cnt[S]==k) {
        if(S&1) {
            x.a[id[S]][id[(S>>1)|(1<<(p-1))]]++;
        } else {
            rep(i,0,p-1) if(S&(1<<i)) {
                int NS=((S^(1<<i))>>1)|(1<<(p-1));
                x.a[id[S]][id[NS]]++;
            }
        }
    }
    int T=0;
    for(reg int j=p-1;j>=p-k;j--) T|=1<<j;
    f[0][id[T]]=1;
    res.Get1();
    n-=k;
    int t=n;
    while(t) {
        if(t&1) res=res*x;
        x=x*x;
        t>>=1;
    }
    rep(i,0,0) rep(j,1,sc) rep(o,1,sc) (ans[i][o]+=f[i][j]*res.a[j][o])%=P;
    T=0;
    rep(j,p-k,p-1) T|=1<<j;
    printf("%d\n",ans[0][id[T]]);
}
 
bool ed;
 
int main(){
    //printf("%.2lf\n",(&ed-&be)/1024.0/1024.0);
    n=rd(),k=rd(),p=rd();
    Solve();
}
 
 
 
 
 

\ [\ \]

\ [\ \]

L [BZOJ3195] [Jxoi2012]奇妙な道路

点が奇数でない前にタイトルが距離、直線エッジ数選択DP、各点の辺の数を定義します

 

const int N=80,P=1000000007;
 
 
int n,m,k;
 
ll dp[31][1<<8][31];
ll C[N][N];
 
 
 
int main(){
    n=rd(),m=rd(),k=rd();
    k=min(k,n);
    C[0][0]=1;
    rep(i,1,N-1) {
        C[i][0]=1;
        rep(j,1,N-1) C[i][j]=(C[i-1][j-1]+C[i-1][j])%P;
    }
    dp[0][0][0]=1;
    rep(i,1,k-1) {
        int A=(1<<i)-1;
        rep(S,0,A) {
            int t=0;
            rep(j,0,i-1) if(S&(1<<j)) t++;
            rep(R,0,A) {
                int NS=(S^R)|((t&1)<<i);
                rep(j,0,m) {
                    for(reg int d=j+t;d<=m;d+=2) {
                        (dp[i][NS][d]+=C[(d-j-t)/2+i-1][i-1]*dp[i-1][R][j]%P)%=P;
                    }
                }
            }
        }
    }
    int A=(1<<k)-1;
    rep(i,k,n-1) {
        rep(S,0,A) {
            int t=0;
            rep(j,0,k-1) if(S&(1<<j)) t++;
            rep(R,0,A) if((R&1)==(S&1)) {
                int NS=((S^R)>>1)|((t&1)<<(k-1));
                rep(j,0,m) {
                    for(reg int d=j+t;d<=m;d+=2) {
                        (dp[i][NS][d]+=C[(d-j-t)/2+k-1][k-1]*dp[i-1][R][j]%P)%=P;
                    }
                }
            }
        }
    }
    ll ans=dp[n-1][0][m];
    printf("%lld\n",ans);
}
 
 

おすすめ

転載: www.cnblogs.com/chasedeath/p/11665098.html