從前往後不好做, 那就直接從後往前
考慮設 \(f[i][j]\) 為在第一張圖中屬於 \(i\) 集合, 在第二張圖中屬於 \(j\) 集合的點的個數
這樣會 mle , 但是又發現有用的 \((i, j)\) 不會很多, 直接 \(map\) 存下來就行了
轉化為切比雪夫距離之後直接從起點 bfs , 把橫縱座標離散化之後存在 set 中, 找到乙個就刪掉他, 這樣就可以保證 bfs 的複雜度是對的了
然後對於每個點算一次貢獻
發現乙個點對會算兩次, 最後把答案除以二就行了
互相包含的區間是沒有用的, 證明的話考慮把小的那個區間挖出去
然後就可以把所有的區間變成左端點和右端點都單調遞增的區間了
那麼乙個區間控制的範圍就是他的左端點到 min(他的右端點, 下乙個區間的左端點 - 1)
設 \(f[i][j]\) 為前 \(i\) 個點控制的範圍中放置了 \(j\) 個 1 並且合法的方案
列舉乙個 \(k\) 然後從 \(f[i - 1][j - k]\) 轉移過來, 乘個組合數就行了
複雜度 \(o(n^3)\) , 但根據網上題解的說法, 複雜度是 \(o(n ^ 2)\) 的
有點沒講清楚細節, 放下**吧
#include #include #include #include const int n = 3e3 + 5;
const int mod = 1e9 + 7;
using namespace std;
int n, m, a[n], l[n], r[n], vis[n], sum[n], c[n][n], f[n][n], mx[n], len[n];
struct node
} p[n];
char s[n];
template < typename t >
inline t read()
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * w;
}int main()
printf("%d\n", f[m][sum[n]]);
return 0;
}
ARC068 簡要題解
任意一面朝上直接 5 6 5 6 或者 6 5 6 5 然後就沒了 首先把牌張數大於三張的丟到三張以下 設還有兩張的有 k 個 如果 k 是 2 的倍數,那麼可以直接全扔了 如果不是,需要找到乙個只有一張牌的扔掉才能把這 k 個扔掉 拿個桶記一下 長度 geq len 的區間中必然存在 len 的倍...
ARC063 簡要題解
模擬即可 算下有多少個極大差就行了 考慮乙個點到另乙個點的路徑是什麼情況 必然是一段上公升的加一段下降的,單增單減也行 然後就可以考慮乙個貪心策略了 每次選出最小的,給他周圍沒有附權值的附乙個 這個最小點權值 1 的權值 不難發現這樣是滿足上面那個條件的 不合法情況中間判一下就行 考試考過,想出來了...
ARC058 簡要題解
暴力列舉然後 check 一下 設左上角的點座標為 1,h 右下角的點座標為 w,1 補集轉化之後就只用求必須經過左下角那個矩形的方案數了 考慮無論怎麼走必須要從矩形右邊的那一條 b,a b,1 線段經過 列舉一下最後經過的哪個點即可 妙補集轉化之後求不存在滿足題意條件的方案數 看到資料範圍容易想到...