csp2019 Emiya家今天的飯

2021-09-29 23:35:39 字數 3286 閱讀 8031

作為提高組d2t

1d2t1

d2t1

,比去年難

所以這道題我打的特別的差

這道題我們很顯然可以看到可以打乙個暴力

複雜度o(n

∗n!)

o(n*n!)

o(n∗n!

)我考場上就達到了這裡——我太菜了

void

dfs(

int u,ll plus)

dfs(u+

1,plus)

;rep

(i,1

,m)if

(a[u]

[i])

}int

main()

因為每一行只能選乙個,所以我們可以每行爆搜找選哪個(或者不選),隨後判斷行不行

這道題一拿到題就覺得是dpdp

dp,但是沒想出來轉移方程,想要拿到64分,我們需要把m

mm=2,3的情況拆成兩種來討論,當m=2

m=2m=

2時,用f[i

][j]

[k

]f[i][j][k]

f[i][j

][k]

表示第i

ii行,第一種食材用了j

jj次,第二種用了k

kk次,可以顯然得到乙個轉移方程f[i

][j]

[k]=

su

mf[i][j][k]=sum\

f[i][j

][k]

=sum

當m =3

m=3m=

3時就是四位dpdp

dp

if

(m==2)

rep(i,

1,n)

ans=

(ans+f[n]

[i][i]

)%mod;

printf

("%lld\n"

,ans);}

if(m==3)

rep(i,

0,n)

rep(j,

0,n)

rep(k,

0,n)

printf

("%lld\n"

,ans)

;}

我們換一種想法,我們把所有可能的情況先算出來,然後再把不符合條件的都減去,怎麼算減去的呢,我們可以想到超過一半的只可能有一種菜,我們先迴圈那種菜再第幾列(col),其他的看成一種菜,那麼我們設計狀態f[i

][j]

[k

]f[i][j][k]

f[i][j

][k]

表示前i

ii道菜,超過一半的菜有j

jj道,剩下的選了k

kk道,那麼轉移方程就是f[i

][j]

[k]=

su

mf[i][j][k]=sum\

f[i][j

][k]

=sum

ans=1;

rep(i,

1,n)

rep(col,

1,m)

rep(i,

0,n)

rep(j,

0,n)

}printf

("%lld\n"

,(ans-

1+mod)

%mod)

;

我們發現,我們最後統計的時候是和j

jj,k

kk沒有關係的,我們只要知道他們的差就可以了,所以我們可以優化掉一維,複雜度變成了o(n

2m

)o(n^2m)

o(n2m)

,可以過啦!

轉移就變成了f[i

][j]

=sum

f[i][j]=sum\

f[i][j

]=su

m但是第二維有可能是負的,所以要整體平移

# include

# include

# include

# include

# include

# include

# include

# include

# include

# include

# include

# include

# include

# define rep(i,a,b) for(int i=a;i<=b;i++)

# define _rep(i,a,b) for(int i=a;i>=b;i--)

using

namespace std;

const

int n=

5e3+5;

const

int zero=

110;

const

int mod=

998244353

;typedef

long

long ll;

template

<

typename t>

void

read

(t &x)

int n,m;

int a[n]

[n];

ll f[45]

[45][

45],g[45][

45][45

][45]

,s[n]

,h[45][

45][45

],dp[zero][2

*zero+10]

;int cnt[n]

,tot;

ll ans;

void

dfs(

int u,ll plus)

dfs(u+

1,plus)

;rep

(i,1

,m)if

(a[u]

[i])

}int

main()

rep(col,

1,m)

rep(i,

1,n)ans=

(ans-dp[n]

[i+zero]

+mod)

%mod;

}printf

("%lld\n"

,(ans-

1+mod)

%mod)

;return0;

}

這道題其實64分不難,但是我特別的菜只打了暴力,所以只有32。。。

所以要好好練一練dpdp

dp

CSP2019 Emiya 家今天的飯

題面 luogu 題解 容斥 dp 首先題意是這樣的 給乙個 n times m 的矩陣,每一行只能選乙個,每一列選的總數不能超過選的總數的一半。求總方案數 考慮容斥 總方案數減去不合法方案數 總方案數顯然 設每一行的總數為 sum i ans prod sum i 1 1 減一是因為不能不做乙個菜...

CSP2019 Emiya 家今天的飯

鏈結 顯然根據性質最多的菜品不超過總數量的一半,可以考慮補集轉化 即計算有乙個菜品超過數量一半的方案數,再用總方案數減 總方案數顯然可以乙個揹包搞定 然而我去年就是因為總方案數沒求對掛了 然後考慮求超過一半的方案數 列舉當前哪個菜品是超過一半的 有乙個顯然的dp f 表示當前到第i行最多的菜品選了j...

csp2019 Emiya家今天的飯題解

qwq 由於窩太菜了,實在是不會,所以在題解的幫助下過掉了這道題。寫此部落格來整理一下思路 傳送簡化一下題意 現在有 n 行 m 列數,選 k 個數的合法方案需滿足 1.一行最多選乙個 2.一列最多選 lfloor frac rfloor 個數 當然,如果你在某一行裡選了0,就相當於沒有在這一行裡選...