Pizza Serparation
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<vector> #include<algorithm> #include<iostream> #include<map> #include<queue> using std::vector; using std::queue; using std::map; using std::sort; using std::string; #define read(x) scanf("%d",&x) #define reads(x) scanf("%s",x) int cmp(const void * x, const void * y) { #define datatype int datatype dx = *((datatype *)(x)), dy = *((datatype *)(y)); //x < y return dx > dy ? 1 : -1; #undef datatype } int a[400], nex[400]; int main() { #ifndef ONLINE_JUDGE freopen("input.txt", "r", stdin); #endif int n; read(n); for (int i = 0; i < n; i++) { read(a[i]); nex[i] = i + 1; } nex[n - 1] = 0; int ans = 0x3FFFFFFF; for (int i = 0; i < n; i++) { int sum = 0; for (int j = i;; j = nex[j]) { sum += a[j]; if (sum >= 180) break; } if (2 * (sum - 180) < ans) ans = 2 * (sum - 180); } printf("%d ", ans); return 0; }
XK Segments
STL真是手残拯救者
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<vector> #include<algorithm> #include<iostream> #include<map> #include<queue> #include<string> using std::vector; using std::queue; using std::map; using std::sort; using std::string; using std::lower_bound; using std::upper_bound; #define read(x) scanf("%d", &x) #define reads(x) scanf("%s", x) #define write(x) printf("%d ", x) #define writes(x) printf("%s ", x) #define writeln(x) printf("%d ", x) #define writesln(x) printf("%s ", x) typedef long long llint; /*data structure*/ /*data structure*/ int cmp(const void * x, const void * y) { #define datatype int datatype dx = *((datatype *)(x)), dy = *((datatype *)(y)); //x < y return dx > dy ? 1 : -1; #undef datatype } /*global variable*/ map<llint, int> mp; vector<llint> v; int sum[100005]; /*global variable*/ int main() { #ifndef ONLINE_JUDGE freopen("input.txt", "r", stdin); #endif int n; llint a, ap, h, l, b, x, k; while (scanf("%d%lld%lld", &n, &x, &k) != EOF) { mp.clear(); v.clear(); for (int i = 0; i < n; i++) { scanf("%lld", &a); if (mp.find(a) == mp.end()) v.push_back(a); mp[a]++; } sort(v.begin(), v.end()); sum[0] = mp[v[0]]; for (int i = 1; i < v.size(); i++) sum[i] = sum[i - 1] + mp[v[i]]; llint ans = 0; for (int i = 0; i < v.size(); i++) { a = v[i]; if (a % x == 0) ap = a; else ap = a - a % x + x; if (k == 0) { h = ap - 1; l = a; } else { ap += x * (k - 1); l = ap; h = ap + x - 1; } if (l > h) continue; int s = lower_bound(v.begin(), v.end(), l) - v.begin(), e = lower_bound(v.begin(), v.end(), h) - v.begin(); if (e == v.end() - v.begin()) e--; if (v[e] > h) e--; if (s == v.end() - v.begin()) continue; ans += (llint)mp[a] * (llint)(sum[e] - sum[s] + mp[v[s]]); } printf("%lld ", ans); } return 0; }
Square Subsets
首先,其中本来就是完全平方数的数,爱取多少取多少,不影响结果,只需最终结果乘以2^a[i]
对于不是完全平方数的数,只需关心其取了奇数个还是偶数个,具体数目不影响结果,因此可以看成只取0个或1个,最终结果乘以2^(a[i]-1)。
将1-70的数分解质因数,记录每个数的各个因子有奇数个还是偶数个。
1-70间的质数共19个,用0-2^19-1表示所有状态,第i为为1表示第i个质数有奇数个,为0表示有偶数个。
dp[i]表示达到i这种质因子奇偶状态的方法数,dp[0]表示完全平方数的方法数。
最终结果减1,去掉空集。
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<vector> #include<algorithm> #include<iostream> #include<map> #include<queue> #include<string> using std::vector; using std::queue; using std::map; using std::sort; using std::string; using std::lower_bound; using std::upper_bound; #define read(x) scanf("%d", &x) #define reads(x) scanf("%s", x) #define write(x) printf("%d ", x) #define writes(x) printf("%s ", x) #define writeln(x) printf("%d ", x) #define writesln(x) printf("%s ", x) #define fillchar(x, a) memset(x, a, sizeof(x)) typedef long long llint; /*data structure*/ /*data structure*/ int cmp(const void * x, const void * y) { #define datatype int datatype dx = *((datatype *)(x)), dy = *((datatype *)(y)); //x < y return dx > dy ? 1 : -1; #undef datatype } /*global variable*/ const int p[19] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67}; const llint mod = 1000000007; int a[80], v[80][19]; llint dp[2][1 << 19]; /*global variable*/ int main() { #ifndef ONLINE_JUDGE freopen("input.txt", "r", stdin); #endif int n, x; read(n); fillchar(a, 0); fillchar(v, 0); for (int i = 0; i < n; i++) { read(x); a[x]++; } int multp = 0; for (int i = 1; i <= 8; i++) { multp += a[i * i]; a[i * i] = 0; } for (int i = 1; i <= 70; i++) { if (a[i]) multp += (a[i] - 1); } for (int i = 1; i <= 70; i++) { x = i; for (int j = 0; j < 19; j++) { while (x % p[j] == 0) { v[i][j] = 1 - v[i][j]; x /= p[j]; } } } fillchar(dp, 0); dp[0][0] = 1; int last = 0, cur; for (int i = 1; i <= 70; i++) { if (a[i] == 0) continue; cur = 1 - last; for (int j = 0; j < (1 << 19); j++) dp[cur][j] = 0; for (int j = 0; j < (1 << 19); j++) { int state = j; if (dp[last][state] == 0) continue; for (int k = 0; k < 19; k++) { state ^= (v[i][k] << k); } dp[cur][state] = (dp[cur][state] + dp[last][j]) % mod; } for (int j = 0; j < (1 << 19); j++) { dp[cur][j] = (dp[cur][j] + dp[last][j]) % mod; } last = cur; } llint ans = dp[last][0]; for (int i = 0; i < multp; i++) { ans = ans * 2 % mod; } printf("%lld ", ans - 1); return 0; }
String Mark
设f(s)为用字符串a组合能产生比s小的字符串的个数,答案为f(b)-f(a)-1,一位一位算就可以了。
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<vector> #include<algorithm> #include<iostream> #include<map> #include<queue> #include<string> #include<functional> #include<iostream> using std::priority_queue; using std::vector; using std::queue; using std::map; using std::sort; using std::string; using std::lower_bound; using std::upper_bound; using std::cin; using std::cout; using std::endl; #define fillchar(x, a) memset(x, a, sizeof(x)) typedef long long lint; /*data structure*/ /*data structure*/ int cmp(const void * x, const void * y) { #define datatype int datatype dx = *((datatype *)(x)), dy = *((datatype *)(y)); //x < y return dx > dy ? 1 : -1; #undef datatype } /*global variable*/ char a[1000005], b[1000005]; lint fac[1000005], ifac[1000005]; int cnt[26], n; const lint mod = 1000000007; /*global variable*/ /*function*/ inline lint pow(lint a, lint b, lint p) { lint rtn = 1; while (b) { if (b & 1) rtn = rtn * a % p; a = a * a % p; b >>= 1; } return rtn; } lint f(char * s) { fillchar(cnt, 0); for (int i = 0; i < n; i++) cnt[a[i] - 'a']++; lint div = 1; for (int i = 0; i < 26; i++) div = div * ifac[cnt[i]] % mod; lint rtn = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < s[i] - 'a'; j++) { if (cnt[j]) { rtn = (rtn + fac[n - i - 1] * cnt[j] % mod * div % mod) % mod; } } if (cnt[s[i] - 'a'] == 0) return rtn; div = div * cnt[s[i] - 'a'] % mod; cnt[s[i] - 'a']--; } return rtn; } /*function*/ int main() { #ifndef ONLINE_JUDGE freopen("input.txt", "r", stdin); #endif std::ios::sync_with_stdio(0), cin.tie(0); cin >> a >> b; n = strlen(a); fac[0] = ifac[0] = 1; for (int i = 1; i <= n; i++) { fac[i] = fac[i - 1] * i % mod; ifac[i] = pow(fac[i], mod - 2, mod); } cout << (f(b) - f(a) - 1 + mod) % mod << endl; return 0; }
Eyes Closed
每个线段里随机选个数,选出来的数期望为线段里的数的平均数,设为a。对于长度为l的线段里的一个数字x,其保持不变的概率为(l-1)/l,被选出来交换的概率为1/l,则其期望为ex=x*(l-1)/l+a/l,即操作后线段里每个数字的期望为原数字乘以一个常数再加一个常数,可以用线段树来实现这个操作,把lazy标记分成两部分即可。
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<vector> #include<algorithm> #include<iostream> #include<map> #include<queue> #include<string> using std::vector; using std::queue; using std::map; using std::sort; using std::string; using std::lower_bound; using std::upper_bound; #define read(x) scanf("%d", &x) #define reads(x) scanf("%s", x) #define write(x) printf("%d ", x) #define writes(x) printf("%s ", x) #define writeln(x) printf("%d ", x) #define writesln(x) printf("%s ", x) #define fillchar(x, a) memset(x, a, sizeof(x)) typedef long long llint; /*data structure*/ template <class T> class SegmentTree { public: T dat, lazym, lazyp; int leftBorder, rightBorder, mid; SegmentTree * leftSon, * rightSon; SegmentTree() { leftBorder = rightBorder = -1; leftSon = rightSon = NULL; } void pushdown(); void pushup(); void Build(T *, int, int); void Modify(int, int, T, T); T Query(int, int); void Free(); }; template<class T> void SegmentTree<T>::pushdown() { if ((lazym != 1 || lazyp != (T)0) && leftBorder != rightBorder) { leftSon->dat = leftSon->dat * lazym + lazyp * (leftSon->rightBorder - leftSon->leftBorder + 1); rightSon->dat = rightSon->dat * lazym + lazyp * (rightSon->rightBorder - rightSon->leftBorder + 1); leftSon->lazym *= lazym; leftSon->lazyp = leftSon->lazyp * lazym + lazyp; rightSon->lazym *= lazym; rightSon->lazyp = rightSon->lazyp * lazym + lazyp; } lazym = (T)1; lazyp = (T)0; } template<class T> void SegmentTree<T>::pushup() { dat = leftSon->dat + rightSon->dat; } template<class T> void SegmentTree<T>::Build(T * S, int l, int r) { if (l > r) { return; } lazym = (T)1; lazyp = (T)0; leftBorder = l; rightBorder = r; mid = (leftBorder + rightBorder) >> 1; if (l == r) { dat = S[l]; return; } leftSon = new SegmentTree; leftSon->Build(S, l, mid); rightSon = new SegmentTree; rightSon->Build(S, mid + 1, r); pushup(); } template<class T> void SegmentTree<T>::Modify(int l, int r, T mult, T plus) { if (l > r || l < leftBorder || rightBorder < r) { return; } if (leftBorder == l && rightBorder == r) { dat = dat * mult + plus * (rightBorder - leftBorder + 1); lazym *= mult; lazyp = lazyp * mult + plus; return; } pushdown(); if (r <= mid) { leftSon->Modify(l, r, mult, plus); } else if (mid < l) { rightSon->Modify(l, r, mult, plus); } else { leftSon->Modify(l, mid, mult, plus); rightSon->Modify(mid + 1, r, mult, plus); } pushup(); } template<class T> T SegmentTree<T>::Query(int l, int r) { if (l > r || l < leftBorder || rightBorder < r) { return dat; } pushdown(); if (l == leftBorder && r == rightBorder) { return dat; } if (r <= mid) { return leftSon->Query(l, r); } else if (mid < l) { return rightSon->Query(l, r); } else { return leftSon->Query(l, mid) + rightSon->Query(mid + 1, r); } } template<class T> void SegmentTree<T>::Free() { if (leftSon != NULL) { leftSon->Free(); } if (rightSon != NULL) { rightSon->Free(); } delete leftSon; delete rightSon; } /*data structure*/ int cmp(const void * x, const void * y) { #define datatype int datatype dx = *((datatype *)(x)), dy = *((datatype *)(y)); //x < y return dx > dy ? 1 : -1; #undef datatype } /*global variable*/ SegmentTree<double> st; double a[100005]; /*global variable*/ int main() { #ifndef ONLINE_JUDGE freopen("input.txt", "r", stdin); #endif int n, q; read(n); read(q); for (int i = 0; i < n; i++) scanf("%lf", &a[i]); st.Build(a, 0, n - 1); int t, l1, l2, l, r1, r2, r; for (int i = 0; i < q; i++) { read(t); if (t == 1) { read(l1); read(r1); read(l2); read(r2); l1--, r1--, l2--, r2--; double sum1 = st.Query(l1, r1), sum2 = st.Query(l2, r2); double ave1 = sum1 / (r1 - l1 + 1.0), ave2 = sum2 / (r2 - l2 + 1.0); st.Modify(l1, r1, (r1 - l1) / (r1 - l1 + 1.0), ave2 / (r1 - l1 + 1.0)); st.Modify(l2, r2, (r2 - l2) / (r2 - l2 + 1.0), ave1 / (r2 - l2 + 1.0)); } else { read(l); read(r); l--, r--; double ans = st.Query(l, r); printf("%.7lf ", ans); } } return 0; }