你有n個點(0~n-1),按順序造成一個環,初始時你在0的位子,你隨機順時針走一步或者逆時針走一步,node
一旦你走到一個點後,環上全部點都被通過至少一次後,你就必須停下來。ios
問你最後停留在m這個位子的機率是多少。c++
注意輸出的答案是前綴積。數組
有意思的機率題。ide
讀懂題意後發現這道題不難,模擬下能夠發如今最後落在(1~n-1)的位子是等機率的,落在0這個位子是不可能的(除非n==1)。優化
#include <iostream> #include <vector> #include <queue> #include <algorithm> using namespace std; #define pb push_back #define fi first #define se second #define debug(x) cerr<<#x << " := " << x << endl; #define bug cerr<<"-----------------------"<<endl; #define FOR(a, b, c) for(int a = b; a <= c; ++ a) typedef long long ll; typedef long double ld; typedef pair<int, int> pii; typedef pair<ll, ll> pll; template<class T> void _R(T &x) { cin >> x; } void _R(int &x) { scanf("%d", &x); } void _R(ll &x) { scanf("%lld", &x); } void _R(double &x) { scanf("%lf", &x); } void _R(char &x) { scanf(" %c", &x); } void _R(char *x) { scanf("%s", x); } void R() {} template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); } template<typename T> inline T read(T&x){ x=0;int f=0;char ch=getchar(); while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x=f?-x:x; } const int inf = 0x3f3f3f3f; const int mod = 1e9+7; /**********showtime************/ ll ksm(ll a, ll b) { ll res = 1; while(b > 0) { if(b & 1) res = res * a % mod; a = a * a % mod; b = b >> 1; } return res; } int main(){ int T; scanf("%d", &T); ll res = 1; while(T--){ ll n,m; scanf("%lld%lld", &n, &m); if(n == 1 && m == 0) res = res; else { if(m == 0) res = res * 0; else { res = res * ksm(n-1, mod-2) % mod; } } printf("%lld\n", res); } return 0; }
BMspa
在一個無向圖中,找出一個權值爲第K小的最小團,最小團的定義爲選出的公共節點間有邊直接聯通。debug
感受實現起來不太難。既然要選擇第K小的,咱們能夠從小到大作。每次經過最小的一個最小團擴展,能夠利用bitset優化判斷擴展的可行性。3d
即利用優先隊列,從其中取出的第k個就是答案。code
有點像dji找最短路
#include<bits/stdc++.h> using namespace std; #define pb push_back #define fi first #define se second #define debug(x) cerr<<#x << " := " << x << endl; #define bug cerr<<"-----------------------"<<endl; #define FOR(a, b, c) for(int a = b; a <= c; ++ a) typedef long long ll; typedef long double ld; typedef pair<int, int> pii; typedef pair<ll, ll> pll; template<class T> void _R(T &x) { cin >> x; } void _R(int &x) { scanf("%d", &x); } void _R(ll &x) { scanf("%lld", &x); } void _R(double &x) { scanf("%lf", &x); } void _R(char &x) { scanf(" %c", &x); } void _R(char *x) { scanf("%s", x); } void R() {} template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); } template<typename T> inline T read(T&x){ x=0;int f=0;char ch=getchar(); while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x=f?-x:x; } const int inf = 0x3f3f3f3f; const int mod = 1e9+7; /**********showtime************/ const int maxn = 109; char str[maxn]; struct node{ ll val; bitset<109>bs; bool operator<(const node & o) const{ return val > o.val; } }a[maxn]; int main(){ int n,k; scanf("%d%d", &n, &k); for(int i=1; i<=n; i++) { scanf("%lld", &a[i].val); } for(int i=1; i<=n; i++) { scanf("%s", str+1); for(int j=1; j<=n; j++) { if(str[j] == '1')a[i].bs.set(j); } } priority_queue<node>que; node s; s.val = 0; s.bs.reset(); que.push(s); int flag = 0;ll res; while(!que.empty()) { node u = que.top(); que.pop(); k -- ; if(k == 0) { flag = 1; res = u.val; break; } int mx = 1; for(int i=1; i<=n; i++) { if(u.bs[i] == 1) mx = i + 1; } for(int i=mx; i<=n; i++) { if((u.bs & a[i].bs) == u.bs) { u.bs.set(i); u.val += a[i].val; que.push(u); u.bs.reset(i); u.val -= a[i].val; } } } if(flag) printf("%lld\n", res); else puts("-1"); return 0; }
線段樹,dp
比賽時過的,雙向搜索下降複雜度(隊友搞的,我還沒搞)
dp
比賽時過的。DP出面積,找出次大的
(隊友搞的,我還沒搞)
有一個長度爲1E9,值爲{-1,1}的數組,保證只有n(<1e6)個區間等於1,且1的個數小於1e7。
求有多少對區間的區間和大於0。
首先把被答案區間所包含的點都找出來。最多隻有3e7個點。怎麼找?
從小到達遍歷數組,把每一個區間向右擴展的長度找出來,
從大到小遍歷數組,把每一個區間向左擴展的長度找出來。
而後計算每一個點的前綴和。在一個點前面且前綴和小於當前點的前綴和的一個點對應ans++。
因爲前綴和的變化大小爲1,因此不用樹狀數組便可完成。
#include <bits/stdc++.h> using namespace std; #define pb push_back #define fi first #define se second #define debug(x) cerr<<#x << " := " << x << endl; #define bug cerr<<"-----------------------"<<endl; #define FOR(a, b, c) for(int a = b; a <= c; ++ a) typedef long long ll; typedef long double ld; typedef pair<int, int> pii; typedef pair<ll, ll> pll; template<class T> void _R(T &x) { cin >> x; } void _R(int &x) { scanf("%d", &x); } void _R(ll &x) { scanf("%lld", &x); } void _R(double &x) { scanf("%lf", &x); } void _R(char &x) { scanf(" %c", &x); } void _R(char *x) { scanf("%s", x); } void R() {} template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); } template<typename T> inline T read(T&x){ x=0;int f=0;char ch=getchar(); while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x=f?-x:x; } const int inf = 0x3f3f3f3f; const ll inff = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9+7; /**********showtime************/ const int maxm = 2e7+9; const int maxn = 1e6+9; int le[maxn],ri[maxn]; int lto[maxn],rto[maxn]; ll f[maxm]; int g(int x) { return x + 10000000; } int main(){ int n; scanf("%d", &n); for(int i=1; i<=n; i++) scanf("%d%d", &le[i], &ri[i]); int sum = 0; /// 向右擴展 le[n+1] = 1000000000; for(int i=1; i<=n; i++) { sum += ri[i] - le[i] + 1; rto[i] = min(sum, le[i+1] - ri[i] - 1); sum -= le[i+1] - ri[i] - 1; if(sum < 0) sum = 0; } /// 向左擴展 sum = 0; ri[0] = -1; for(int i=n; i>=1; i--) { sum += ri[i] - le[i] + 1; lto[i] = min(sum , le[i] - ri[i-1] -1); sum -= le[i] - ri[i-1] - 1; if(sum < 0) sum = 0; } ///計算每一個點的前綴和。lowsum保存前綴和比當前點小的個數 ll ans = 0, lowsum = 0; int s = 0, pos = 0; f[g(0)] = 1; for(int i=1; i<=n; i++) { for(int j=max(pos, le[i] - lto[i]); j<=ri[i] + rto[i]; j++) { if(j>=le[i] && j <= ri[i]) { lowsum += f[g(s)]; s++; f[g(s)]++; ans += lowsum; } else { s--; lowsum -= f[g(s)]; f[g(s)]++; ans += lowsum; } // cout<<j<<" "<<lowsum<<endl; pos = j+1; } } // cout<<endl; printf("%lld\n", ans); return 0; }