2014多校聯合四(HDU 4901 HDU 4902 HDU 4905),hdu4902

來源:互聯網
上載者:User

2014多校聯合四(HDU 4901 HDU 4902 HDU 4905),hdu4902

HDU 4901 The Romantic Hero

題意: 一串數字a  找一個位置分開  前面為S'後面為T'  從這兩個集合中分別選出子集S和T  使得S中元素的“異或”值等於T中元素的“且”值  問一共幾種方案

思路:

由於a[i]只有1024  那麼無論怎麼運算都不可能大於2047  又因為S和T有一個明顯的分界  所以我們可以想到利用dp分左右兩邊處理  令l[i][j]表示從左到i位置且一定選取a[i]的情況下異或值為j的方案數  r[i][j]類似  令sl[i][j]表示l[1~i][j]的和  sr[i][j]類似  這些都可以通過正反掃描得到  最後為了防止重複計數  可以通過sl[i][j]*r[i+1][j]或者sr[i][j]*l[i-1][j]來更新答案

代碼:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define N 1010#define mod 1000000007#define M 2048int l[N][M], r[N][M], sl[N][M], sr[N][M], a[N];int t, n, ans;int main() {int i, j, v;scanf("%d", &t);while (t--) {scanf("%d", &n);for (i = 1; i <= n; i++)scanf("%d", &a[i]);memset(l, 0, sizeof(l));memset(sl, 0, sizeof(sl));l[1][a[1]] = sl[1][a[1]] = 1;for (i = 2; i <= n; i++) {for (j = 0; j < M; j++) {v = j ^ a[i];l[i][v] = sl[i - 1][j];}l[i][a[i]] = (l[i][a[i]] + 1) % mod;for (j = 0; j < M; j++)sl[i][j] = (sl[i - 1][j] + l[i][j]) % mod;}memset(r, 0, sizeof(r));memset(sr, 0, sizeof(sr));r[n][a[n]] = sr[n][a[n]] = 1;for (i = n - 1; i >= 1; i--) {for (j = 0; j < M; j++) {v = j & a[i];r[i][v] = (r[i][v] + sr[i + 1][j]) % mod;}r[i][a[i]] = (r[i][a[i]] + 1) % mod;for (j = 0; j < M; j++)sr[i][j] = (sr[i + 1][j] + r[i][j]) % mod;}ans = 0;for (i = 1; i < n; i++) {for (j = 0; j < M; j++) {if (sl[i][j] && r[i + 1][j]) {ans = ((__int64 ) sl[i][j] * r[i + 1][j] % mod + ans) % mod;}}}printf("%d\n", ans);}return 0;}


HDU 4902 Nice boat

題意: n個數字  m個操作  每次1操作將[l,r]區間所有值改為x  每次2操作將[l,r]中大於x的數改為與x取gcd

思路:明顯是線段樹  不過想不出對於一段區間進來兩次2操作如何合并  想想要更新到葉子節點(這裡的葉子指的是一段連續區間的數字相同)  就覺得線段樹也最佳化不到哪去  於是開始玩暴力  結果500+ms就過了…

暴力方法很簡單  因為如果1操作覆蓋了f這個點  那麼這個1操作前面的所有操作都沒有意義  因此暴力枚舉n個位置  對於每個位置從後到前掃描操作  如果遇到1操作就break  然後把掃描進來的2操作暴力做一遍  可以類比棧來實現

代碼:

#include<cstdio>#include<algorithm>using namespace std;__int64 last[100010], a[100010], num[100010];int l[100010], r[100010], op[100010];int n, m, t;__int64 func(__int64 fa) {if (fa < 0)return -fa;return fa;}__int64 kgcd(__int64 fa, __int64 fb) {if (fa == 0)return fb;if (fb == 0)return fa;if (!(fa & 1) && !(fb & 1))return kgcd(fa >> 1, fb >> 1) << 1;else if (!(fb & 1))return kgcd(fa, fb >> 1);else if (!(fa & 1))return kgcd(fa >> 1, fb);elsereturn kgcd(func(fa - fb), min(fa, fb));}int main() {int i, j, top;__int64 ans;scanf("%d", &t);for (; t; t--) {scanf("%d", &n);for (i = 1; i <= n; i++)scanf("%I64d", &a[i]);scanf("%d", &m);for (i = 1; i <= m; i++)scanf("%d%d%d%I64d", &op[i], &l[i], &r[i], &num[i]);for (i = 1; i <= n; i++) {top = 0;ans = a[i];for (j = m; j >= 1; j--) {if (i >= l[j] && i <= r[j]) {if (op[j] == 1) {ans = num[j];break;} else {last[++top] = num[j];}}}for (j = top; j > 0; j--) {if (ans > last[j])ans = kgcd(ans, last[j]);}printf("%I64d ", ans);}putchar('\n');}return 0;}

HDU 4905 The Little Devil II

陳題不多說了  四邊形最佳化

注意:不要迷信什麼快速gcd  我隊友因為他TLE了好幾次  為什麼呢?  演算法是錯的?  不是的…  在期望情況下明顯快速gcd更優  不過這題的gcd是一個區間裡所有數的gcd  由於數字是隨機的  所以很容易就產生小數字  因此還是輾轉相除靠譜

代碼:

#include<cstdio>#include<cstring>#include<algorithm>typedef __int64 ll;using namespace std;const int M = 3010;int a[M], s[M][M], g[M][M];ll dp[M][M];int n;template<class T>inline void scan_d(T &ret) {char c;ret = 0;while ((c = getchar()) < '0' || c > '9');while (c >= '0' && c <= '9')ret = ret * 10 + (c - '0'), c = getchar();}inline int abs(int a) {return a < 0 ? -a : a;}int gcd(int a, int b) {if (a < b)swap(a, b);int i;while (b) {i = a % b;a = b;b = i;}return a;}inline void solve() {int l, i, j, k;memset(dp, 0, sizeof(dp));for (i = 1; i <= n; i++)s[i][i] = i;for (l = 1; l <= n - 1; l++) {for (i = 1; i <= n - l; i++) {j = i + l;for (k = s[i][j - 1]; k <= s[i + 1][j]; k++) {if (k < j && dp[i][j] < dp[i][k] + dp[k + 1][j] + g[i][j]) {dp[i][j] = dp[i][k] + dp[k + 1][j] + g[i][j];s[i][j] = k;}}}}}int main() {int min, i, j;int T;scan_d(T);while (T--) {scan_d(n);ll max = 0;ll s = 0;for (i = 1; i <= n; i++) {scan_d(a[i]);s += a[i];}for (i = 1; i <= n; i++) {g[i][i] = a[i];for (j = i + 1; j <= n; j++) {g[i][j] = gcd(g[i][j - 1], a[j]);}}solve();printf("%I64d\n", s + dp[1][n]);}return 0;}


PS:比賽的時候腦子還是不太靈TAT  總是看到別人出題才深入思考… sad…  同時團隊配合還要加強!! 加油!!




聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.