序列選數問題合集

2021-08-28 02:44:57 字數 3989 閱讀 1052

bzoj 1283

給出乙個長度為n的正整數序列ci,求乙個子串行,使得原序列中任意長度為m的子串中被選出的元素不超過k 個,並且選出的元素之和最大。

n<=1000,k,m<=100,ci<=20000。

分析把數列串成一串,從 i

ii 連向 i+m

i+mi+

m,費用cic_

ci​,流量1

11。s

ss連1

11,流量k

kk即可。也即選擇乙個數之後,其後k

kk個之後便無影響。

loj 6079 山東集訓 養貓

限制改為連續m

mm個不超過k1k1

k1個,不少於k2k2

k2個分析

由於穿過每個截面的流量相同,要求上方有至少k2k2

k2個就是要求下方至多k1−

k2

k1-k2

k1−k

2個,在下方加乙個上界即可

zjoi 2013 防守戰線

每個位置的數可以選若干次,限制形如[l,

r]

[l, r]

[l,r

]中至少選k

kk個,求最小和

分析兩種理解方式:

(1)用差分的方法使得每個變數僅在兩個式子中出現,且係數一正一負。

這是一種經典的做法,從志願者招募一題開始出現。若是使用這種做法,需要係數矩陣每一列不為0的數連續且相等。如此例:

a1a2

a3a4

a5a601

1001

0111

0110

1111

1000

10這樣差分之後便使得每個變數出現兩次,且係數分別為±

1\pm1

±1。但本題中的性質則略有變化。本題為每一行的非零數連續且相同,如此例:

a1a2

a3a4

a5a601

1100

1111

0000

0011

1111

00所以我們需要將其旋轉90∘

90^\circ

90∘,也就是對偶。

對偶之後即可變為之前的圖,差分即可。

(2)用字首和轉化,方法同chefbook。

原線性規劃形如:

設s

is_i

si​表示1−i

1-i1−

i選了幾個數

最小化 :

∑ (s

i−si

−1)∗

ci

\sum(s_i-s_)*c_i

∑(si​−

si−1

​)∗c

i​滿足:sr−

sl−1

>=d

ks_r-s_ >= d_k

sr​−sl

−1​>=d

k​s i−

si−1

>=0

s_i-s_i-1 >= 0

si​−si

​−1>=0

s

i>=0

s_i >= 0

si​>=0

注意到每個限制都只有兩個變數,且引數分別為±

1\pm1

±1。如下例:

a1a2

a3a4

a5a60-1

0100

00-11

00-10

0001

-1010

00則將其對偶之後(行列交換),每個變數恰出現兩次,且係數分別為±

1\pm1

±1費用流即可

在3的基礎上,增加一種限制形如[l, r]中至多選k個,求最小/最大和

在4的基礎上,增加一種限制,每個位置有乙個至多選的次數,求最大/最小和

完整描述如下:

有乙個數列,在這個數列中選一些數。位置i

ii的數可以被選擇t

it_i

ti​次。現在有若干限制,形如在區間[l,

r]

[l, r]

[l,r

]中至少/至多選出幾個數,求最小/最大和。

乙個數列,限制形如區間[l,

r]

[l, r]

[l,r

]的和至少為$d $,求最少選出幾個數。

//t1, bzoj1283

#include #include #include #include #include #include #define maxn 1050

#define il inline

#define pb push_back

#define ri register int

#define mod

#define inf (1<<28)

using namespace std;

typedef long long ll;

typedef long double ld;

struct node pool[maxn<<4], *h[maxn<<4], *pre[maxn<<4];

int n, m, k, cnt, w[maxn], s, t, maxf, minc, inq[maxn<<4], val[maxn<<4], c[maxn<<4], q[maxn<<5];

il void adde(int u, int v, int c, int w) , h[u] = p;

*q = node , h[v] = q;

}bool spfa() }}

if(val[t] <= -2e9) return 0;

maxf += val[t], minc += val[t]*c[t];

int u = t;

while(u != s)

return 1;

}int main()

###1-2

//t2 養貓

#include #include #include #include #include #include #include #include #include #include #define inf (1<<29)

#define llinf (1ll<<60)

#define maxn 5050

using namespace std;

/*第一行四個整數 n,k,ms,me

第二行包含 n n n 個整數,代表 si

第三行包含 n 個整數,代表 ei。*/

int n, k, ms, me, cnt, sl[maxn], ea[maxn], ss, s, t, maxn, minn, flow;

int q[maxn<<2], c[maxn<<2], inq[maxn<<2], go[maxn<<2];

long long sum, w[maxn<<2], fee;

struct nodepool[maxn<<4], *h[maxn<<2], *pre[maxn<<2];

inline void addedge(int u, int v, int c, int w, int ty) , h[u] = p1;

*p2 = node, h[v] = p2;

}bool spfa()

} }if(w[t] <= iiss) return 0;

flow += c[t], fee += w[t]*c[t];

int u = t;

while(u != ss)

return 1;

}int main()

for(int i = 1; i <= n; i++)

while(spfa());

printf("%lld\n", sum+fee);

for(int i = 1; i <= n; i++)

if(go[i]) printf("e");

else printf("s");

return 0;

}

NOIP提高組 選數問題

在麥克雷的面前有n個數,以及乙個r c的矩陣。現在他的任務是從n個數中取出r c個,並填入這個矩陣中。矩陣每一行的法值為本行最大值與最小值的差,而整個矩陣的法值為每一行的法值的最大值。現在,麥克雷想知道矩陣的最小法值是多少。顯然排序後選擇答案是不會影響答案的,分析題意後可以發現乙個明顯的性質 對於某...

week3 A 選數問題

given n positive numbers,select exactly k of them that sums to s.wonders how many ways to get it 給n個數,選擇k個數相加的和為s,找出所有數的組合。the first line,an integer t...

c 實現 遞迴選數問題

給定乙個陣列,裡面有n位正整數,要從這個陣列裡面選取k個數,使得它們的和為s,問有多少種可能的取法 第一行,乙個整數t t 100 指示測試用例的數量。對於每個情況,有兩行。第一行,三個整數表示n,k和s.其中k n 16.第二行n個整數表示n個元素的陣列。資料保證所有數字都可以以 32 位整數儲存...