upsloved
有乙個長為\(n\)的環,一開始位於\(0\),每次隨機向前或者向後走,求最後乙個走到\(m\)的概率
ps:這題實際上求的是所有詢問的字首積
實際上概率相等(俺也不知道為啥)如果\(m!=0\),則概率是\(\frac 1 \),特判\(n=1,m=0\)就行了
**不放了
solved at 03:54(+2)
有乙個無限長的序列,一開始位於\(0\),每次概率均等地往前走\(1\)到\(k\)步,求經過\(n\)的概率
\(1<=n<=1e18, 1<=k<=1000\)
如果\(n=-1\)表示求\(n\)趨近於正無窮時的概率
顯然\(dp[i] = \sum\limits_^dp[j]\)
這是個線性遞推式,我們賽中bm搞過去了...
\(n=-1\)時小資料打表發現是\(\frac 2 \)
矩陣快速冪是\(k^3\log(n)\)的,據說可以利用轉移矩陣和特徵方程的聯絡優化成\(k^2\log(n)\)的,並不是很懂,可以搜叉姐**看一看
**也沒啥好放的
upsloved
\(n\)個點的帶點權的圖,求權值第\(k\)小的完全子圖的權值\(1<=n<=100, 1<=k<=1e6)\)
看著咖啡雞的**恍然大悟,咖啡雞nb
用優先佇列儲存當前完全子圖,然後嘗試往這個圖里塞乙個點,為避免重複只塞下標比當前完全子圖最大點下標還要大的點,複雜度大概是\(k\log(k)+kn^2/64\)
#include using namespace std;
using bs = bitset<105>;
using ll = long long;
struct node
};int s[105][105], n, a[105], k;
bs f[105];
int main()
for(int i = 0; i < n; ++i)
} priority_queuepq;
bs p;
p.reset();
pq.push();
while(!pq.empty())
int pos = 0;
for(int i = 0; i < n; ++i)
if(u.mask[i])
pos = i + 1;
for(int i = pos; i < n; ++i) if((f[i] & u.mask) == u.mask) );
u.mask[i] = 0;
} }puts("-1");
return 0;
}
upsolved
你有乙個\(n*m\)的\(01\)矩陣,\(1\)代表牆,你每次可以往下,左,右走(不能往上,也不能走回頭路)
有兩種操作
1.修改\(i, j\)位置的矩陣狀態
2.詢問從\(1, a\)走到\(n, b\)的方案數
設\(dp[l][r][i][j]\)代表從\(l, i\)走到\(r,j\)的方案數
顯然\(dp[l][r][i][j] = \sum\limits_^mdp[l][x][i][k]*dp[x+1][r][k][j]\),\(x\)是\(l\)到\(r-1\)之間的任意乙個值
因為不能走回頭路,相當於列舉怎麼從\(x\)走到\(x+1\)的
然後這個東西顯然可以用線段樹,支援\(o(m^3\log(n))\)修改, \(o(1)\)查詢
總複雜度是\(o(q*m^3\log(n)+m^3n)\)
#include using namespace std;
const int mod = 1e9 + 7, n = 5e4 + 10;
int n, m, q, b[n][10], x, y, z;
char s[14];
struct matrix
}tree[n << 2];
void pushup(int rt)
void calc(int b, matrix &c)
}void build(int rt, int l, int r)
int mid = l + r >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
pushup(rt);
}void update(int rt, int l, int r, int pos)
int mid = l + r >> 1;
if(pos <= mid)
update(rt << 1, l, mid, pos);
else
update(rt << 1 | 1, mid + 1, r, pos);
pushup(rt);
}int main()
build(1, 1, n);
while(q--)
else
} return 0;
}
solved at 02:38(+3)
有\(2n\)個人,把他們分為大小各為\(n\)的兩個集合,不在同乙個集合裡的人會獲得貢獻\(v_\),求最大貢獻
\((1<=n<=14)\)
比賽的時候並沒有發現\(c_^\)只有4e7, 可以直接\(o(n*c_^)\)dfs過去
比賽的時候我寫了個折半搜尋,打了四個表,實際上複雜度也是\(o(n*c_^)\)的...
折半的兩個東西拼起來的時候要一些騷操作,不然很容易變成\(2*n*c_^\)的或者是\(n*2^\)的
#include using namespace std;
const int n = 10 + (1 << 14);
long long dp[n], dp2[n];
long long p[14][n], p2[14][n], ans;
int a[28][28], n, t[n], f[n];
int c[n], tot;
vectorv[15];
int main()
} tot = (1 << n) - 1;
c[0] = 0;
v[0].push_back(0);
for(int i = 1; i <= tot; ++i)
f[0] = 1;
t[f[0]] = 0;
for(int i = 1; i < n; ++i)
for(int i = 0; i < n; ++i)
}p[i][mask] = val;
} }for(int i = 0; i < n; ++i)
}p2[i][mask] = val;
} }for(int mask = 0; mask <= tot; ++mask)
} }for(int mask = 0; mask <= tot; ++mask)
} }for(int mask = 0; mask <= tot; ++mask)
} printf("%lld\n", ans);
return 0;
}
solved at 01:00(+2)
有乙個\(n*m\)的\(01\)矩陣,求面積第二大的全\(1\)子矩陣面積\(1<=n,m<=1000\)
最大的是用懸線法\(o(nm)\)處理出來,第二大的也差不多,把每個位置對應的最大的要麼行減一,要麼列減一,第二大的肯定在這些裡面
注意可能很多位置的最大全\(1\)子矩陣是同乙個矩陣,標記掉就好了
#include using namespace std;
const int n = 1010;
int a[n][n], d[n][n], s[n][n], s2[n][n], mx, mx2, n, m, vis[n][n];
int main()
for(int j = 1; j <= m; ++j)
} for(int i = 1; i <= n; ++i)
} for(int i = 1; i <= n; ++i)
} for(int i = 1; i <= n; ++i)
} printf("%d\n", mx2);
return 0;
}
upsolved
開場就有人過,看了半天不怎麼會,沒想到是個暴力
參考部落格
2019牛客多校第二場
蒙特卡洛 猜答案 注意答案要累乘 最大的可以用rmq rmqrm q做然後挖掉四個角分別再做一次即可 掛一下大佬的鏈結 最重要的是學會了字首和查詢相差為1 11的時候的奇技淫巧 include include define fo i,a,b for i a i b i define fd i,a,b...
2019牛客多校第二場
乙個0到n 1的環,初始在0,每次隨機前進或後退一格,當所有點都訪問過就結束,問結束時站在k的概率是多少。注意輸出的是字首積 一開始站在0,最後顯然不可能在0,剩下n 1格,隨機數打表發現概率相同,都為 frac include using namespace std typedef long lo...
牛客多校第二場 J farm
輸入描述 the first line of input contains 3 integers n,m,t n m 1000000,t 1000000 for the next n lines,each line contains m integers in range 1,n m denotin...