好几天才做完这几道题。。效率贼低。。还有一个插头DP和一个大搜索没做。 插头DP学完之后来填,大搜索嘛。。什么时候想练码力了再写吧。 总体感觉不是特别难,没有像今年r2的那种神级毒瘤题。。
R1 day1
shrew
乍一看被唬住了。然后就开始寻找问题性质 看数据范围->一定是枚举啊。。 所有数字的总和一定能整除 再想了一会儿,发现角上只有一种消法,然后就写了一发纯暴力。
Code
1 | //Code by Lucida |
calc
之前学BSGS的时候做过,本来想迅速写完,结果写完了pow_mod和exgcd之后就卡住了。。无语啊。想了一会儿,模模糊糊记得好像是个算出以内的值,hash之后再枚举?总之没回忆起来。
为了防止忘,还是写下来吧。
BSGS
解 由费马小定理,,所以方程左边的值以为第一个周期,然后开始循环。(好像是P-2?)但是实现的时候感觉算到简单一些。 令,则 固定,这样只需枚举,看看有没有符合条件的即可。
- 算出的,存在
HashSet里面 - 枚举,查找。如果找到了就返回。 特殊情况!当的时候总是无解。。需要特判。
Code
1 | //Code by Lucida |
paint
太弱了。。这种题想了一中午都没想出来。。 对于每个区间,维护一个左端点颜色,一个右端点颜色,就可以合并了(好像看到了一点捉迷藏括号序列的影子啊。。)
Code
1 | //Code by Lucida |
R1 day2
missile
太弱了,被这题从2016克到了2017。
首先第一问,不用说,是CDQ分治。
然后我就WA了好久。因为之前写CDQ分治,虽说也是统计前面对后面的影响,但是要求的是总和之类的问题。所以我就顺手写了
1
DC(l,mid),DC(mid+1,r);
然后查了很长时间才查出来。 第二问,仍旧CDQ分治,要找出有多少有多少种方案包含某个点,然后除以总方案数就是这个点的概率。 就要记一下一个点前面有多少点可以转移到它,它点可以转移到后面多少个点,相乘就行了。 第一种没问题,第二种就没办法了。最后发现,似乎只能把序列翻转求。 改完之后,还是WA。最后发现,是先按照第一关键字再按第二关键字比较的。所以即使相同也有可能不累加。惨痛的教训啊!
Code
1 | //Code by Lucida |
job
费用流直接上,结果因为没用LL,WA了一次,而且还是全WA。 一定要算好一个变量的取值范围!!! 如果考场上出现这种情况,那就真是>>>>了。
Code
1 | //Code by Lucida |
maze
不会做。。。
用三进制数表示对陷阱的了解情况。
状态是表示对陷阱的了解情况为,在位置,血量为,走出的最大概率。
转移的时候,如果碰到了未知的陷阱,可以根据p[]中目前可能存在的状况求出陷阱两种属性分别的概率。
写完之后90。换个枚举顺序就100了??why??
Tips
不要被题目吓到。冷静下来好好分析。
Code
1 | //Code by Lucida |
R2 day1
game
一开始看错题了。看对了之后又理解错了。 对于一次游戏,终止局面一定是相邻的黑子白子靠在一起,这还是能看出来的。 按照标解,黑子右移或者白子左移都没有意义,因为可以模仿。所以只考虑黑子左移或者白子右移的情况。 把空格看成石子的话,问题就变成了:有堆石子,一次可以从堆拿走任意多的石子,不能拿的输,问有多少种先手必胜策略。 这种博弈称为Nim-K,结论和Bash博弈类似:当每堆石子的每个二进制位为1的个数都分别能整除,则先手必败。 然后可以根据这个来DP。定义为处理完二进制前位,石子总和为的必败方案数目(当石子堆顺序不同也算不同),然后枚举的倍数转移。 最终必败的方案总和为 乘的那个组合数的含义为: 已经确定了每堆石子的个数,只需确定每堆第一个石子的位置就能确定出一个方案。而共有个位置可供选择,要选个。
但其实这个转化是有问题的?
Code
1 | //Code by Lucida |
mindist
树网的核
Code
1 | //Code by Lucida |
mars
R2 day2
snake
the file name has no special meanings
这是个什么梗啊。。然后又不会做 先用分数规划求出到每个出入口的最小危险值。 然后建图,S到奇数点,偶数点到T,流量为最小危险值。 在对应的出入口之间连INF。跑出最小割就是答案。
Tips
实数二分最好记答案,实数二分的range要在合法的情况下尽量小,要么就得调小eps。否则误差会大 对于不可达的奇数点或者偶数点,如果和S,T没有连INF就会WA?
Code
1 | //Code by Lucida |
repair
学习了一个虚树。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138//Code by Lucida
template <class T> inline bool chkmx(T &a,const T &b){return a<b?a=b,1:0;}
template <class T> inline bool chkmn(T &a,const T &b){return a>b?a=b,1:0;}
using std::swap;
using std::min;
using std::sort;
typedef long long LL;
const int MAXN=250000+10,LOG=21;
const LL INF=1e15;
int n,K,h[MAXN];
struct Graph
{
private:
int id[MAXN],ec,us[MAXN],T;
public:
struct Edge{int to,v,pre;}e[MAXN<<1];
void clear(){ec=1,++T;}
void check(int pos){if(us[pos]!=T) us[pos]=T,id[pos]=0;}
void Adde(int f,int t,int v)
{
check(f),check(t);
e[++ec].to=t;e[ec].v=v;e[ec].pre=id[f];id[f]=ec;
e[++ec].to=f;e[ec].v=v;e[ec].pre=id[t];id[t]=ec;
}
void Adde(int f,int t)
{
check(f),check(t);
e[++ec].to=t;e[ec].pre=id[f];id[f]=ec;
}
int operator [](int x){check(x);return id[x];}
Edge &operator ()(int i){return e[i];}
void out()
{
for(int i=0;i<=n;i++)
for(int j=id[i];j;j=e[j].pre)
printf("%d %d\n",i,e[j].to);
}
}real,virt;
LL mine[MAXN]/*minedge*/;
int dfs[MAXN<<1],dc,li[MAXN],ro[MAXN],dep[MAXN];
void DFS(int pos)
{
dfs[++dc]=pos;li[pos]=ro[pos]=dc;
for(int i=real[pos];i;i=real(i).pre)
{
int u=real(i).to;
if(li[u]) continue;
dep[u]=dep[pos]+1;
mine[u]=min(mine[pos],(LL)real(i).v);
DFS(u);ro[pos]=ro[u];dfs[++dc]=pos;
}
}
int f[MAXN<<1][LOG],log_2[MAXN<<1];
void ST()
{
log_2[0]=-1;
for(int i=1;i<=dc;i++) f[i][0]=dfs[i],log_2[i]=log_2[i>>1]+1;
for(int j=1;j<=log_2[dc];j++)
for(int i=1;i<=dc-(1<<j)+1;i++)
{
int pl=f[i][j-1],pr=f[i+(1<<(j-1))][j-1];
f[i][j]=dep[pl]<dep[pr]?pl:pr;
}
}
int LCA(int p1,int p2)
{
if(!p1 || !p2) return 0;
static int i,pl,pr;
p1=li[p1],p2=li[p2];
if(p1>p2) swap(p1,p2);
i=log_2[p2-p1+1],pl=f[p1][i],pr=f[p2-(1<<i)+1][i];
return dep[pl]<dep[pr]?pl:pr;
}
inline bool cmp(const int &a,const int &b){return li[a]<li[b];}
LL DP(int pos)
{
if(!virt[pos]) return mine[pos];
LL res=0;
for(int i=virt[pos];i;i=virt(i).pre)
{
int u=virt(i).to;
res+=DP(u);
}
chkmn(res,mine[pos]);return res;
}
LL solve()
{
static int stack[MAXN],top;
sort(h+1,h+1+K,cmp);
//剪枝
int hc=0;for(int i=1;i<=K;i++)
if(!hc || ro[h[hc]]<li[h[i]]) h[++hc]=h[i];
virt.clear();
stack[top=0]=0;
for(int i=1;i<=hc;i++)
{
for(int lca=LCA(stack[top],h[i]);stack[top]!=lca;)
{
if(dep[lca]>dep[stack[top]])
stack[++top]=lca;
else if(dep[lca]<=dep[stack[top]])
{
virt.Adde(dep[stack[top-1]]>=dep[lca]?stack[top-1]:lca,stack[top]);
if(dep[stack[top]]==dep[lca]) stack[top]=lca;
else top--;
}
}
stack[++top]=h[i];
}
for(;top;top--)
virt.Adde(stack[top-1],stack[top]);
//virt.out();
return DP(0);
}
int main()
{
//freopen("input","r",stdin);
red(n);real.clear();
for(int i=1;i<=n-1;i++)
{
int u,v,w;
red(u),red(v),red(w);
real.Adde(u,v,w);
}
mine[0]=mine[1]=INF,dep[1]=1;
DFS(1);ST();
int m;red(m);
for(int i=1;i<=m;i++)
{
red(K);
for(int j=1;j<=K;j++)
red(h[j]);//h[i]..
printf("%lld\n",solve());
}
return 0;
}