abc 222 題解
阿新 • • 發佈:2021-10-14
E
一個揹包一眼題。
先暴力算出每條邊經過的次數,然後大力01揹包,注意次數為 \(0\) 也要做揹包。
這裡我剛開始的做法時每次 \(dp[i]=dp[i+x]+dp[i-x]\),但這樣還需要將陣列擴大一倍,很麻煩,而且要起來。
#include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #include <vector> #define uint unsigned int #define LL long long using namespace std; const int MAXN = 10005, MAXM = 105, Mod = 998244353; int n, m, k, a[MAXM], c[MAXN], d[MAXN], Fa[MAXN]; int dp[2][MAXN * MAXM * 2]; vector <int> v[MAXN]; void dfs(int x, int fa) { Fa[x] = fa; for(uint i = 0; i < v[x].size(); i ++) { int y = v[x][i]; if(y == fa) continue; d[y] = d[x] + 1; dfs(y, x); } } int main() { int x, y; scanf("%d%d%d", &n, &m, &k); for(int i = 1; i <= m; i ++) scanf("%d", &a[i]); for(int i = 1; i < n; i ++) { scanf("%d%d", &x, &y); v[x].push_back(y); v[y].push_back(x); } dfs(1, -1); for(int i = 1; i < m; i ++) { x = a[i]; y = a[i + 1]; while(x != y) { if(d[x] > d[y]) c[x] ++, x = Fa[x]; else c[y] ++, y = Fa[y]; } } // dp[i][j]=dp[i-1][j-ai]|dp[i-1][j+ai] dp[1][n * m] = 1; for(int i = 2; i <= n; i ++) { for(int j = 0; j <= 2 * n * m; j ++) { dp[i & 1][j] = 0; if(j - c[i] >= 0) dp[i & 1][j] = (dp[i & 1][j] + dp[(i - 1) & 1][j - c[i]]) % Mod; if(j + c[i] <= 2 * n * m) dp[i & 1][j] = (dp[i & 1][j] + dp[(i - 1) & 1][j + c[i]]) % Mod; } } if(n * m + k < 0 || n * m + k > 2 * n * m) printf("0"); // 特判 else printf("%d", dp[n & 1][n * m + k]); return 0; }
其實換個角度,這裡將一種顏色貢獻看為 \(1\),一種看為 \(0\),簡單計算一下會更好打。
#include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #include <vector> #define uint unsigned int #define LL long long using namespace std; const int MAXN = 10005, MAXM = 105, Mod = 998244353; int n, m, k, a[MAXM], c[MAXN], d[MAXN], Fa[MAXN], all; int dp[MAXN * MAXM * 2]; vector <int> v[MAXN]; void dfs(int x, int fa) { Fa[x] = fa; for(uint i = 0; i < v[x].size(); i ++) { int y = v[x][i]; if(y == fa) continue; d[y] = d[x] + 1; dfs(y, x); } } int main() { int x, y; scanf("%d%d%d", &n, &m, &k); d[1] = 1; for(int i = 1; i <= m; i ++) scanf("%d", &a[i]); for(int i = 1; i < n; i ++) { scanf("%d%d", &x, &y); v[x].push_back(y); v[y].push_back(x); } dfs(1, -1); for(int i = 1; i < m; i ++) { x = a[i]; y = a[i + 1]; while(x != y) { if(d[x] > d[y]) c[x] ++, x = Fa[x]; else c[y] ++, y = Fa[y]; } } for(int i = 1; i <= n; i ++) all += c[i]; dp[0] = 1; for(int i = 2; i <= n; i ++) { // 注意這裡 c[i]=0時要進行操作 for(int j = all; j >= c[i]; j --) dp[j] = (dp[j] + dp[j - c[i]]) % Mod; } if(((all + k) & 1) || (all + k) / 2 < 0 || (all + k) / 2 > all) printf("0"); else printf("%d", dp[(all + k) / 2]); return 0; }
F
仙姑著。。。因為沒調出來。。。
G
\(ax=0\pmod b<=>x=0\pmod {\frac {b} {\gcd(b,a)}}\)
\(\frac{x}{a}=0\pmod b<=>x=0\pmod {ab}\)
trick:\(a|b=>b=0\pmod a\)。
推一下式子:
\((10^k-1)*2/9=0\pmod x\)
\(10^k-1=0\ (\mathrm{mod}\ \frac {9x } {\gcd (9x,2)})\)。
\(10^k=1(...)\)
然後這裡用尤拉定理即可,,
#include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #include <vector> #include <iostream> #define LL long long #define uint unsigned int using namespace std; int T, fuck, res = 0x3f3f3f3f; int Gcd(int x, int y) { return y ? Gcd(y, x % y) : x; } int Getphi(int x) { int ans = x, t = sqrt(x); for(int i = 2; i <= t; i ++) { if(x % i == 0) ans = ans / i * (i - 1); while(x % i == 0) x /= i; } if(x > 1) ans = ans / x * (x - 1); return ans; } int Qpow(int x, int y) { int ans = 1; for(; y; y >>= 1) { if(y & 1) ans = (LL)ans * x % fuck; x = (LL)x * x % fuck; } return ans; } int main() { scanf("%d", &T); while(T --) { scanf("%d", &fuck); fuck = 9 * fuck; if(fuck % 2 == 0) fuck >>= 1; res = 0x3f3f3f3f; if(Gcd(fuck, 10) > 1) { printf("-1\n"); continue; } int p = Getphi(fuck), g = sqrt(p);// printf("|%d|", p); for(int i = 1; i <= g; i ++) { if(p % i == 0) { if(Qpow(10, i) == 1) res = min(res, i); if(Qpow(10, p / i) == 1) res = min(res, p / i); } } printf("%d\n", res); } return 0; }