2013 icpc 成都 (5.19)
阿新 • • 發佈:2019-02-20
A - Assignment For Princess
題解
xjb構造就可以了
先1到n兩兩連起來i, i+1的權值為i
接下來在滿足條件的情況下連i, 1的邊
然後在連其他的邊就可以了
程式碼
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define lson l,mid,o<<1
#define rson mid+1,r,o<<1|1
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int, int> P;
typedef pair<P, int> PII;
const LL INF = 0x3f3f3f3f;
const int N = 1e7 + 10;
const LL mod = 1e9 + 7;
const double PI=acos(-1);
queue<int>tot[3];
int sum[110];
int main()
{
int T;
scanf("%d", &T);
for(int t = 1; t <= T; ++t){
printf("Case #%d:\n", t);
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; ++i) tot[i % 3 ].push(i);
sum[1] = 0;
for(int i = 1; i < n; ++i){
printf("%d %d %d\n", i, i + 1, tot[i % 3].front());
sum[i + 1] = (sum[i] + i) % 3;
tot[i % 3].pop();
}
for(int i = n; i > 2; --i){
if(tot[(3 - sum[i]) % 3].empty()) continue;
printf("%d %d %d\n", i, 1, tot[(3 - sum[i]) % 3].front());
tot[(3 - sum[i]) % 3].pop();
}
for(int i = 2; i < n; ++i){
for(int j = i + 2; j <= n; ++j){
if(tot[(sum[j] + 3 - sum[i]) % 3].empty()) continue;
printf("%d %d %d\n", i, j, tot[(sum[j] + 3 - sum[i]) % 3].front());
tot[(sum[j] + 3 - sum[i]) % 3].pop();
}
}
}
return 0;
}
B - Beautiful Soup
C - Clumsy Algorithm
題解
首先通過打表,發現題目中的條件等價於單調遞減的子序列的長度小於3
然後就可以xjbg維護了啊
程式碼
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define lson l,mid,o<<1
#define rson mid+1,r,o<<1|1
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int, int> P;
typedef pair<P, int> PII;
const LL INF = 0x3f3f3f3f;
const int N = 1e7 + 10;
const LL mod = 1e9 + 7;
const double PI=acos(-1);
inline int ab(int x){return x < 0 ? -x : x;}
inline int mm(int x, int p){return x >= p ? x - p : x < 0 ? x + p : x;}
int a[120];
int dp[120][120];
bool vis[120];
int main()
{
int T, n, k;
scanf("%d", &T);
for(int t = 1; t <= T; ++t){
scanf("%d%d", &n, &k);
memset(dp, 0, sizeof dp);
for(int i = 1; i <= k; ++i) scanf("%d", &a[i]);
int now = 0;
memset(vis, false, sizeof vis);
vis[0] = true;
bool flag = true;
for(int i = 1; i <= k; ++i){
if(a[i] > now) now = a[i], vis[a[i]] = true;
else{
if(!vis[a[i] - 1]) flag = false;
else vis[a[i]] = true;
}
}
printf("Case #%d: ", t);
dp[now][k] = flag;
for(int i = now + 1; i <= n; ++i){
dp[i][k] = flag;
for(int j = k + 1; j < i; ++j)
dp[i][j] = mm(dp[i][j - 1] + dp[i - 1][j], mod);
}
int ssum = 0;
for(int i = k; i <= n; ++i) ssum = mm(dp[n][i] + ssum, mod);
printf("%d\n", ssum);
}
return 0;
}
D - Dinner Coming Soon
題解
暴力的dp去維護,按時間循序,因為每一次位置的變化時間必定增加,然後注意結束位置和一些細節
程式碼
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define lson l,mid,o<<1
#define rson mid+1,r,o<<1|1
#define fio ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int, int> P;
typedef pair<int, P> PII;
typedef pair<LL, int> PIII;
const LL INF = 0x3f3f3f3f;
const int N = 1e5 + 10;
const int M = 3e6 + 10;
//const LL mod = 1e9 + 7;
const double PI=acos(-1);
inline LL ab(LL x){return x < 0 ? -x : x;}
inline LL mm(LL x, LL p){return x >= p ? x - p : x < 0 ? x + p : x;}
int mp[210][10];
LL dp[210][10][210][10];
vector<PII>son[210];
int main()
{
int Cas, n, m, b, k, r, t, u, v, c_t, c_c;
scanf("%d", &Cas);
for(int cas = 1; cas <= Cas; ++cas){
scanf("%d%d%d%d%d%d", &n, &m, &b, &k, &r, &t);
for(int i = 0; i < k; ++i)
for(int j = 1; j <= n; ++j)
scanf("%d", &mp[j][i]);
for(int i = 1; i <= n; ++i) son[i].clear();
for(int i = 1; i <= m; ++i){
scanf("%d%d%d%d", &u, &v, &c_t, &c_c);
son[u].push_back({v, {c_t, c_c}});
}
memset(dp, -1, sizeof dp);
dp[1][0][0][0] = r;
LL ans = -1;
for(int h = 0; h <= t; ++h){
for(int now = 1; now < n; ++now){
for(int i = 0; i < k; ++i){
if(now != 1){
for(int j = 0; j < b; ++j){
if(dp[now][i][h][j + 1] >= 0 && dp[now][i][h][j] < dp[now][i][h][j + 1] + mp[now][i])
dp[now][i][h][j] = dp[now][i][h][j + 1] + mp[now][i];
}
for(int j = b; j > 0; --j){
if(dp[now][i][h][j - 1] >= mp[now][i] && dp[now][i][h][j] < dp[now][i][h][j - 1] - mp[now][i])
dp[now][i][h][j] = dp[now][i][h][j - 1] - mp[now][i];
}
}
for(int j = 0; j <= b; ++j){
if(dp[now][i][h][j] == -1) continue;
if(dp[now][i][h][j] > dp[now][(i + 1) %k][h + 1][j])
dp[now][(i + 1) %k][h + 1][j] = dp[now][i][h][j];
for(auto it : son[now])
if(h + it.se.fi <= t && dp[now][i][h][j] - it.se.se > dp[it.fi][i][h + it.se.fi][j])
dp[it.fi][i][h + it.se.fi][j] = dp[now][i][h][j] - it.se.se;
}
}
}
ans = max(ans, dp[n][0][h][0]);
}
printf("Case #%d: ", cas);
if(ans == -1) printf("Forever Alone\n");
else printf("%lld\n", ans);
}
return 0;
}
/*
2
4 4
1 2 1
2 3 1
3 4 1
1 4 0
5 6
1 2 1
1 3 1
1 4 1
1 5 1
3 5 1
4 2 1
*/
E - Exhausted Robot
F - Fibonacci Tree
題解
先判斷圖是否聯通
然後用黑邊去連看最少還需要多少條邊
然後用白邊去連看最多能用多少條邊
然後在判一判就可以了
程式碼
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define lson l,mid,o<<1
#define rson mid+1,r,o<<1|1
#define fio ios::sync_with_stdio(false);cin.tie(0)
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int, int> P;
typedef pair<P, int> PII;
typedef pair<LL, int> PIII;
const LL INF = 0x3f3f3f3f;
const int N = 1e5 + 10;
const int M = 3e6 + 10;
//const LL mod = 1e9 + 7;
const double PI=acos(-1);
inline LL ab(LL x){return x < 0 ? -x : x;}
inline LL mm(LL x, LL p){return x >= p ? x - p : x < 0 ? x + p : x;}
int n, m;
P edge[2][N];
int tot[2];
int fa[N];
int find(int x){
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
bool check1(){
for(int i = 1; i <= n; ++i) fa[i] = i;
int u, v;
for(int i = 0; i < 2; ++i)
for(int j = 1; j <= tot[i]; ++j){
u = find(edge[i][j].fi), v = find(edge[i][j].se);
fa[u] = v;
}
int res = 0;
for(int i = 1; i <= n; ++i) res += (fa[i] == i);
return res == 1;
}
int fib[N];
int check2(){
for(int i = 1; i <= n; ++i) fa[i] = i;
int u, v;
for(int i = 0; i <= 0; ++i)
for(int j = 1; j <= tot[i]; ++j){
u = find(edge[i][j].fi), v = find(edge[i][j].se);
fa[u] = v;
}
int res = 0;
for(int i = 1; i <= n; ++i) res += (fa[i] == i);
return res;
}
int check3(){
for(int i = 1; i <= n; ++i) fa[i] = i;
int u, v;
int res = 0;
for(int i = 1; i <= 1; ++i)
for(int j = 1; j <= tot[i]; ++j){
u = find(edge[i][j].fi), v = find(edge[i][j].se);
if(u != v) res++, fa[u] = v;
}
return res;
}
int main()
{
int cnt = 2;
fib[1] = 1, fib[2] = 2;
for(int i = 3; fib[i - 1] < 1e6; ++i) fib[i] = fib[i - 1] + fib[i - 2], cnt++;
// cout << cnt << endl;
int t, u, v, op;
scanf("%d", &t);
for(int cas = 1; cas <= t; ++cas){
printf("Case #%d: ", cas);
scanf("%d%d", &n, &m);
tot[0] = tot[1] = 0;
for(int i = 1; i <= m; ++i){
scanf("%d%d%d", &u, &v, &op);
edge[op][++tot[op]] = {u, v};
}
if(check1()){
int now = check2() - 1;
int id = lower_bound(fib + 1, fib + cnt + 1, now) - fib;
// cout << now << " " << fib[id] << check3() << endl;
if(check3() >= fib[id]) puts("Yes");
else puts("No");
}
else{
puts("No");
}
}
return 0;
}
/*
2
4 4
1 2 1
2 3 1
3 4 1
1 4 0
5 6
1 2 1
1 3 1
1 4 1
1 5 1
3 5 1
4 2 1
*/
G - GRE Words Revenge
題解
ac自動機加二進位制分組(名字口胡的)
程式碼
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define lson l,mid,o<<1
#define rson mid+1,r,o<<1|1
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int, int> P;
typedef pair<int, P> PII;
const LL INF = 0x3f3f3f3f;
const int N = 1e7 + 10;
const LL mod = 1e9 + 7;
const double PI=acos(-1);
struct Trie{
static const int kN = N;
static const int chN = 2;
int next[kN][chN], fail[kN], tot = 0, root[30], mark[kN], mark1[kN], cnt = 0, si[30];
void init(){
cnt = tot = 0;
}
inline int newcode(){
tot++;
memset(next[tot], 0, sizeof(next[tot]));
mark[tot] = 0;
return tot;
}
void build(int x){
queue <int> que;
que.push(x);
fail[x] = 0;
mark1[x] = 0;
int pos, u, v;
while(!que.empty()){
pos = que.front(); que.pop();
for(int i = 0; i < chN; ++ i){
if(!next[pos][i]) continue;
u = fail[pos], v = next[pos][i];
while(u && !next[u][i]) u = fail[u];
fail[v] = u ? next[u][i] : x;
que.push(v);
mark1[v] = mark1[fail[v]] + mark[v];
}
}
}
void add(char s[], char ch){
root[++cnt] = newcode(), si[cnt] = 1;
int pos = root[cnt];
for(int i = 0; s[i]; ++ i){
if(!next[pos][s[i]-ch]) next[pos][s[i]-ch] = newcode();
pos = next[pos][s[i]-ch];
}
mark[pos]++;
while(si[cnt] == si[cnt - 1]){
unite(root[cnt - 1], root[cnt]);
si[--cnt] <<= 1;
}
build(root[cnt]);
}
LL query(char s[], char ch){
int pos;
LL ret = 0;
for(int id = 1; id <= cnt; ++id){
pos = root[id];
for(int i = 0; s[i]; ++ i){
while(pos && !next[pos][s[i]-ch]) pos = fail[pos];
pos = pos ? next[pos][s[i]-ch] : root[id];
ret += mark1[pos];
}
}
return ret;
}
void unite(int u, int v){
mark[u] += mark[v];
for(int i = 0; i < chN; ++i){
if(!next[u][i] || !next[v][i]) next[u][i] += next[v][i];
else unite(next[u][i], next[v][i]);
}
}
}ac;
char s[N];
set<uLL>st;
int main()
{
int T;
scanf("%d", &T);
uLL v;
for(int t = 1; t <= T; ++t){
int n, now;
LL res = 0;
ac.init();
st.clear();
printf("Case #%d:\n", t);
scanf("%d", &n);
for(int i = 1; i <= n; ++i){
scanf("%s", s);
int len = strlen(s);
now = res % (len - 1);
reverse(s + 1, s + len);
reverse(s + 1, s + len - now);
reverse(s + len - now, s + len);
if(s[0] == '+'){
v = 1;
for(int i = 1; s[i]; ++i) v = v * 31 + s[i] - '0';
if(st.find(v) != st.end()) continue;
else{
st.insert(v);
ac.add(s + 1, '0');
}
}
else{
res = ac.query(s + 1, '0');
printf("%lld\n", res);
}
}
}
return 0;
}