hihoCoder挑戰賽31 題解

2021-08-08 22:52:46 字數 3797 閱讀 6294

時間限制:8000ms

單點時限:1000ms

記憶體限制:256mb

描述 給定n個整數常數c[1], c[2], …, c[n]和乙個整數k。現在需要給2k個整數變數x[1], x[2], …, x[k], y[1], y[2], …, y[k]賦值,滿足

(1)對於所有1 ≤ i ≤ k,都有x[i] ≤ y[i]。

(2)對於所有1 ≤ i ≤ n,都存在至少乙個j (1 ≤ j ≤ k),使得x[j] ≤ c[i] ≤ y[j]。

求出s=(y[1] + y[2] + … + y[k]) - (x[1] + x[2] + … + x[k])的最小值。

輸入 第一行兩個整數n, k。(1 ≤ n, k ≤ 100000)

接下來n行,每行乙個整數c[i]。 (-1000000000 ≤ c[i] ≤ 1000000000)

輸出 輸出乙個整數表示s的最小值。

樣例解釋

x[1]=-5, y[1]=4,

x[2]=10, y[2]=10.

樣例輸入

5 2

-5 0

10 4

0 樣例輸出

9貪心取最小的n-k個間隔

時間限制:11000ms

單點時限:1000ms

記憶體限制:256mb

描述 對於乙個正整數列a[1], … , a[n] (n ≥ 3),如果對於所有2 ≤ i ≤ n - 1,都有a[i-1] + a[i+1] ≥ 2 × a[i],則稱這個數列是美麗的。

現在有乙個正整數列b[1], …, b[n],請計算:將b數列均勻隨機打亂之後,得到的數列是美麗的概率p。

你只需要輸出(p × (n!))mod 1000000007即可。(顯然p × (n!)一定是個整數)

輸入 第一行乙個整數n。 (3 ≤ n ≤ 60)

接下來n行,每行乙個整數b[i]。 (1 ≤ b[i] ≤ 1000000000)

輸出 輸出(p × (n!))mod 1000000007。

考慮最後求的數列一定是先遞減後不變後遞增的

拆成2個數列,dp f[

i][j

][k]

[l] 表示左端的兩個數是 i 和 j,右端的是 k 和 l 的方案數

最小值有 k 個重複則乘上 k!。非最小值至多只能有 2 次重複

初始狀態為數列均為最小值那個值

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

using namespace std;

#define for(i,n) for(int i=1;i<=n;i++)

#define fork(i,k,n) for(int i=k;i<=n;i++)

#define forkd(i,k,n) for(int i=n;i>=k;i--)

#define rep(i,n) for(int i=0;i#define ford(i,n) for(int i=n;i;i--)

#define repd(i,n) for(int i=n;i>=0;i--)

#define forp(x) for(int p=pre[x];p;p=next[p])

#define forpiter(x) for(int &p=iter[x];p;p=next[p])

#define lson (o<<1)

#define rson ((o<<1)+1)

#define mem(a) memset(a,0,sizeof(a));

#define memi(a) memset(a,0x3f,sizeof(a));

#define memi(a) memset(a,128,sizeof(a));

#define memx(a,b) memset(a,b,sizeof(a));

#define inf (0x3f3f3f3f)

#define f (1000000007)

#define pb push_back

#define mp make_pair

#define fi first

#define se second

#define vi vector

#define pi pair

#define si(a) ((a).size())

#define pr(kcase,ans) printf("case #%d: %lld\n",kcase,ans);

#define pri(a,n) for(i,n-1) cout<#define pri2d(a,n,m) for(i,n)

ll add(ll a,ll b)

ll sub(ll a,ll b)

void upd(ll &a,ll b)

inline int read()

while(isdigit(ch))

return x*f;

} #define maxn (70)

ll f[maxn][maxn][maxn][maxn];

ll a[maxn],n;

int main()

f[l][l][l][l]=1;

fork(i,l,n-1)

if (a[i+1]-a[k]>=a[k]-a[l])

}

}ll ans2=0;

for(j,n) for(k,n) for(l,n)

upd(ans2,f[n][j][k][l]);

cout0;}

時間限制:5000ms

單點時限:1000ms

記憶體限制:256mb

描述 01串指的是只有0,1組成的串。對於乙個01串a[1..n],它的逆序對是指這樣的(i,j),滿足1 ≤ i < j ≤ n且a[i] > a[j]。如果乙個01串的逆序對數量為奇數,則稱它是乙個好串。例如,串1010有3個逆序對,它是乙個好串;而串0100有2個逆序對,它不是乙個好串。

定義這樣乙個函式f:對於乙個01串s,如果s可以寫成t1t2…tk的形式(即k個串依次連線),並且所有ti都是好串,那麼定義f(s)的值為這樣的最小的k;否則,定義f(s)=0。

例如:f(1010)=1,因為1010本身是乙個好串。f(101010)=2,因為101010本身不是好串,但它可以拆成101和010。f(110)=0,因為它無法寫成若干個好串的連線。

現在有乙個長為n的01串s,它共有2n-1個非空子序列(s的子串行是指刪去s的若干個數字後(或不刪),剩下的數字按原來順序形成的序列)。你需要計算這些串的f值之和,模1000000007。

例如當s=110時,你需要輸出(f(1)+f(1)+f(0)+f(11)+f(10)+f(10)+f(110)) mod 1000000007。

輸入 輸入一行乙個長度為n的01串。(1 ≤ n ≤ 100000)

輸出 輸出答案模1000000007。

假設 s = t1 · · ·tk,k ≥ 4,其中 ti 都是好串,且 k 取到最小值。則 t1 有奇數個 1,否則

t1t2t3 的逆序對數和 t2t3 的逆序對數的奇偶性不同。所以 t2 有偶數個 0,否則 t1t2 可以合併。

同理,t2 有奇數個 1,t3 有偶數個 0。於是 t1t2t3 的逆序對數為奇數,矛盾。因此最小的 k ≤ 3。

暴力計算不同k出現次數。

hihoCoder挑戰賽C題 永恆遊戲

有乙個定理保證,對於乙個固定的初始局面,不論怎麼操作,要麼可以無限操作下去,要麼在相同步數之後停在相同的局面上。所以只需要模擬100000次即可知道本題答案。定理的證明可以在以下 中找到 定理1.1 include include using namespace std define inf 100...

hihocoder挑戰賽20小記

2016.11.4 晚上六點點開了一場看上去通過人數比較多的hihoround 20 virtual participate了一下。感覺這場還是比較友好的,和我以前做的hihoround只能做一題,或者爆零不一樣。在兩個小時裡寫了3個題 a,b,c d看上去像是個經典問題,但從來沒寫過 幾何基本等於...

hihoCoder挑戰賽12 順子 模擬

時間限制 6000ms 單點時限 1000ms 記憶體限制 256mb 你在賭場裡玩梭哈,已經被發了4張牌,現在你想要知道發下一張牌後你得到順子的概率是多少?假定賭場使用的是一副牌,四種花色的a 2 3 j q k共52張,這副牌只發給你了4張,你的剩下一張牌從剩下48張中任意取出一張。順子指的是點...