A题 签到 但我很奇怪为什么别人跳过A先过了B
B题 将总时间分配给不同论文得到A*Xi的引用数 模拟了一下样例感觉把时间按照1,1,1,......的分法是最优的, 虽然不知道为什么
C题 在A题的基础上加了区间询问 一眼过去非常得分块 但是分不出来....最后是一个主席树的模板题(当然也确实看到了一些oier很莽的分块做法)
D题 长得像数学我就没管它了 其实是个DP技巧题 f[i][j]表示i个球分成j段的乘积和 需要用一个类似前缀和的优化 奇怪的是这个优化没卡住 反而是计算贡献的时候迟迟无法理解式子的正确性。。。总之很神奇。。。
E题 也特别地漂亮。长得很吓人的一道题,还是强制在线。不过考虑到每条边只会被更新一次,所以复杂度是可以保证的。每次在往上连lca的时候只会影响到这条链上处在并查集顶端的点,不知道应该怎么说qaq,开心地上CODE
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 10010
using namespace std;
int edgenum,vet[N],head[N],tim,jie[N],du[N],dep[N];
int fa[N][20],f[N];
int n,m,a,b,x0,y0,z0;
void add(int u,int v){
edgenum++;vet[edgenum]=v;jie[edgenum]=head[u];head[u]=edgenum;
}
int lca(int u,int v){
if(dep[u]<dep[v])swap(u,v);
for(int i=15;i>=0;i--)if(dep[fa[u][i]]>=dep[v])u=fa[u][i];
for(int i=15;i>=0;i--)if(fa[u][i]!=fa[v][i]){
u=fa[u][i];
v=fa[v][i];
}
if(u!=v)return fa[u][0];else return u;
}
void dfs(int u,int ff,int d){
int e=head[u];
fa[u][0]=ff;
dep[u]=d;
for(int i=1;i<=15;i++)fa[u][i]=fa[fa[u][i-1]][i-1];
while(e>0){
int v=vet[e];
if(v!=ff){
dfs(v,u,d+1);
}
e=jie[e];
}
}
int find(int x){
if(x==f[x])return x;
f[x]=find(f[x]);
return f[x];
}
void update(int lcax,int u){
if(u==1 || lcax==u)return;
u=find(u);
while(dep[lcax]+1<=dep[fa[u][0]]){
int v=fa[u][0];
z0^=du[v];
du[v]--;
z0^=du[v];
v=find(v);
f[u]=v;
u=v;
}
}
int main(){
while(scanf("%d%d%d%d%d%d",&n,&m,&a,&b,&x0,&y0)!=EOF){
edgenum=0;memset(head,0,sizeof(head));
tim=0;
memset(du,0,sizeof(du));
memset(fa,0,sizeof(fa));
z0=0;
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
u++;v++;
add(u,v);add(v,u);
du[u]++;du[v]++;
}
for(int i=1;i<=n;i++)z0=z0^du[i],f[i]=i;
int x,y;
dfs(1,0,1);
for(int i=1;i<=m;i++){
x=(a*x0+b*y0+z0)%n;
y=(b*x0+a*y0+z0)%n;
if(i==m)break;
x++;y++;
int u=lca(x,y);
update(u,x);
x0=x-1,y0=y-1;
}
printf("%d %d\n",x,y);
}
}
F题 长得可签到了...确认了一下就写了...就wa了...从来没有深究过有关精度的问题...叉姐的题解:“long double是会挂的”...在没办法的情况下...只有多试错???
G题 string transformation 痛苦地卡了很久 主要还是大脑停止了思考...然后一直试图构造自己的样例方案...一直没发现其实它根本是个no solution...知道ab<->ba之后就可以做了...c字符作为分割标记...每段区间内分别统计a、b的个数是否合法就好
H题 不会做 题解是线性递推+高斯+矩阵快速幂 ....下面是sub老师的CODE
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <set>
#include <map>
#include <iostream>
#include <queue>
#include <cmath>
#define rep(i,n) for(int i=1;i<=n;++i)
using namespace std;
const int N=55,MOD=1e9+7;
int a[N],c[N],n,m;
struct mat{
int a[N][N];
mat operator*(mat p){
mat ret;memset(ret.a,0,sizeof ret.a);
rep(i,n+1)rep(k,n+1)if(a[i][k])rep(j,n+1)
ret.a[i][j]=(ret.a[i][j]+1ll*a[i][k]*p.a[k][j])%MOD;
return ret;
}
}A,S;
int main(){
while(~scanf("%d%d",&n,&m)){
rep(i,n)scanf("%d",a+i);
rep(i,n)scanf("%d",c+i);
rep(i,n){
A.a[1][i]=(c[i]+a[i])%MOD;
rep(j,i-1)A.a[1][i]=(A.a[1][i]+1ll*(MOD-a[i-j])*c[j])%MOD;
}
A.a[1][n+1]=0;
rep(i,n)rep(j,n+1)A.a[i+1][j]=(i==j);
rep(i,n+1)rep(j,n+1)S.a[i][j]=(i==j);
for(;m;m>>=1,A=A*A)
if(m&1)S=S*A;
int ans=S.a[1][1];
rep(i,n)ans=(ans+1ll*(MOD-S.a[i+1][1])*c[i]%MOD)%MOD;
printf("%d\n",ans);
}
}
I题 考虑到每次最多只有一个零能对LIS产生贡献 于是每次答案要不是L 要不是L+1 预处理出分别以i作为开头或结尾的lis dp值 然后对每一个fi 找出它下一个零后面那段区间中 gj+fi=L 同时aj尽可能大 那就把gj作为下标 一个遍历就好了 要特别注意零贡献在两端 以及n=1的情况 也是特别漂亮的一道题
J题 题意大致是给出一个染色图 一条边中至少需要染一个点 然后染色点点权值要尽可能小...一开始还以为是个匹配的图论...也是停止了思考...草稿乱打了一阵之后去正确模拟了一下样例...突然就明白了...
K题 也没什么好说的...那就不说了...
... ... ......吓得我赶紧把所有有趣的comment点了一遍...我感觉从此都有阴影了...(update:默默删去了cf那天的吐槽 看出这个阴影面积真的很大。。。感人了。。。)
anyway。。。。。还是很pleasing的。。。。
今天虽然早起了但是没能把H做掉...另外做得是之前差的青蛙题和细菌题,,,,hw2的blog就不更了...日子都过去好久了quq