文章目录
- 前言
- 题目解析
- 序列计数(sequence)
- T2 网格选点(grid)
- T3 孤立点集(isolated)
- 代码
- T1
- T2
- T3
- 总结
前言
180pts
30+50+100
rnk10
题目比较简单的一场考试。
不太满意。
T3是做过的原题,切了不算啥本事,而且还花了1.5h。
T1、2都只混了个暴力分,有点惨。
题目解析
序列计数(sequence)
耳目一新的莫队题。
就是没想到…
由于T3整了太长时间,后来又先去了T2,这题从10:30才开始摸,做的时候时间不是很够了。
一开始就写个 ∑\sum∑ 然后开始化。
从那一刻我这道题几乎就已经没了,后来一直在各种NTT,甚至还想到了NTT配合分块这种诡异的东西。
不要先入为主!
当一个思路不断的转化后遇到一个难以解决的问题时,不一定要在这个问题上死磕,也应该试试推翻之前的思路,从新审视一下这个题。
既然有组合数,也不是没想过杨辉三角,但是几乎只在大脑里存在了一瞬间…
设 S(x,y)=∑i=0xCyiS(x,y)=\sum_{i=0}^xC_y^iS(x,y)=∑i=0xCyi。
(l,r,x)(l,r,x)(l,r,x) 的答案就是 S(r,x)−S(l−1,x)S(r,x)-S(l-1,x)S(r,x)−S(l−1,x)。
考虑如何移动 x,yx,yx,y 指针。
(虽然依然有 x≤yx\le yx≤y,但叫它左右指针还是不太贴切了)
S(x,y+1)=S(x,y)+Cy+1xS(x,y+1)=S(x,y)+C_{y+1}^xS(x,y+1)=S(x,y)+Cy+1x
S(x,y−1)=S(x,y)−CyxS(x,y-1)=S(x,y)-C_y^xS(x,y−1)=S(x,y)−Cyx
S(x+1,y)=2×S(x,y)−CyxS(x+1,y)=2\times S(x,y)-C_y^xS(x+1,y)=2×S(x,y)−Cyx
S(x−1,y)=S(x,y)+Cyx−12S(x-1,y)=\frac{S(x,y)+C_y^{x-1}}{2}S(x−1,y)=2S(x,y)+Cyx−1
前两个显然,第三个想想杨辉三角的转移即可得,第四个是第三个的逆过程。
然后就做完了。
T2 网格选点(grid)
怎么又是grid
本次考试可以说主攻的一道题。
可以说,题解PPT里的每行字我考场几乎都推出来了。
然后呢?
然后呢!
这个玩意证出来反向单调之后咋办啊…
上完线段树这个东西变得很难搞,每个点都转移区间都不一样。
现在也不知道怎么实现…
不过这个题单调性是推出来的而不是“感性理解”的,也算是一个突破吧。
T3 孤立点集(isolated)
见到这个原题我是一点也不高兴。
当时我就被这个毒瘤东西恶心坏了。
但是毕竟是原题,还是最先做的。
(努力调用内存…)
差不多想起来了做法,但是忘记为什么可以这么做了…
然后发现自己第三问连怎么做也忘记了…
想了好久想起来可以暴力删点(与其说是想起来了不如说是做出来了)。
代码写起来不太难,匈牙利还是很香的,比dinic好写不知道多少,考场能用还是要用。
但是前前后后还是花了1.5h…
当时我做这个题的时候就是似懂非懂的,难怪如今再做的时候困难。
需要用一个 dilworth 定理,当时好像我根本就没理解这个定理。
代码
T1
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("OK\n")
inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}
const int N=4e5+100;
const int B=150;
const int inf=1e9;
const int mod=998244353;int n,m;
int o=2e5,w;
inline ll ksm(ll x,ll k){ll res(1);while(k){if(k&1) res=res*x%mod;x=x*x%mod;k>>=1;}return res;
}
ll jc[N],ni[N];
int bel[N];
void init(){int n=o;w=sqrt(n);jc[0]=1;for(int i=1;i<=n;i++) jc[i]=jc[i-1]*i%mod;ni[n]=ksm(jc[n],mod-2);for(int i=n-1;i>=0;i--) ni[i]=ni[i+1]*(i+1)%mod;for(int i=1;i<=n;i++) bel[i]=(i-1)/w+1;//for(int i=1;i<=n;i++) printf("i=%d bel=%d\n",i,bel[i]);return;
}
inline ll C(int n,int m){return jc[n]*ni[m]%mod*ni[n-m]%mod;
}
int L,R;
struct query{int x,y,id,op;bool operator < (const query oth)const{if(bel[x]!=bel[oth.x]) return bel[x]<bel[oth.x];else{if(bel[x]&1) return y<oth.y;else return y>oth.y;}}
}q[N];
int ans[N],tot;
int x,y;
ll now;
int clo;
inline ll calc(int nx,int ny){while(nx<x) now=(now-C(y,x--)+mod)%mod,++clo; while(nx>x) now=(now+C(y,++x))%mod,++clo;while(ny>y) now=(now*2-C(y++,x)+mod)%mod,++clo;while(ny<y) now=((now+C(--y,x))*ni[2])%mod,++clo;//printf("x=%d y=%d calc=%lld\n",x,y,now);return now;
}signed main(){freopen("sequence.in","r",stdin);freopen("sequence.out","w",stdout);//freopen("a.in","r",stdin);//freopen("a.out","w",stdout);n=read();init();for(int i=1;i<=n;i++){int l=read(),r=read(),x=read();q[++tot]=(query){l-1,x,i,-1};q[++tot]=(query){r,x,i,1};}sort(q+1,q+1+tot);//x=1,y=0;now=1;for(int i=1;i<=tot;i++){ans[q[i].id]=(ans[q[i].id]+q[i].op*calc(q[i].x,q[i].y)+mod)%mod;//printf("(%d %d) clock=%d\n",q[i].x,q[i].y,clo);}for(int i=1;i<=n;i++) printf("%d\n",ans[i]);//printf("clock=%d\n",clo);return 0;
}
/*
3
5 3 2
1 2 0
*/
T2
暂无qwq
但我可以把暴力贴过来
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("OK\n")
inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}
const int N=2e5+100;
const int B=920;
const int inf=1e9;
const int mod=998244353;int n,m;
struct node{int x,y;bool operator < (const node oth)const{return x<oth.x;}
}p[N];
int f[N];
ll x[N],y[N];
ll dp[N];signed main(){freopen("grid.in","r",stdin);freopen("grid.out","w",stdout);n=read();m=read();for(int i=1;i<=n;i++) p[i].x=read(),p[i].y=read();sort(p+1,p+1+n);for(int i=1;i<=n;i++) x[i]=p[i].x,y[i]=p[i].y;int mx(0);ll ans=2e18;for(int i=1;i<=n;i++){f[i]=1;for(int j=1;j<i;j++){if(y[j]<y[i]) f[i]=max(f[i],f[j]+1);}mx=max(mx,f[i]);}for(int i=1;i<=n;i++){if(f[i]==1) dp[i]=x[i]*y[i];else dp[i]=2e18;for(int j=1;j<i;j++){if(f[i]==f[j]+1&&y[j]<y[i]){dp[i]=min(dp[i],dp[j]+(x[i]-x[j])*(y[i]-y[j]));}}if(f[i]==mx) ans=min(ans,dp[i]+(m-x[i])*(m-y[i]));}printf("%lld\n",ans);return 0;
}
/*
5 2
2 4
1 5
1 2
2 3
3 4
3 5
*/
T3
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("OK\n")
inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}
const int N=230;
const int B=920;
const int inf=1e9;
const int mod=998244353;int n,m;
struct node{int to,nxt;
}p[N*N*2];
int fi[N],cnt;
inline void addline(int x,int y){p[++cnt]=(node){y,fi[x]};fi[x]=cnt;
}int mat[N],vis[N],tim;
int f[N][N],ban[N];
bool find(int x){if(ban[x]) return false;if(vis[x]==tim) return false;vis[x]=tim;for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(ban[to]) continue;if(!mat[to]||find(mat[to])){mat[x]=to;mat[to]=x;return true;}}return false;
}
int hangry(){memset(mat,0,sizeof(mat));memset(vis,0,sizeof(vis));int res(0);for(int i=1;i<=n;i++) tim=i,res+=find(i);//for(int i=1;i<=n;i++) printf("i=%d mat=%d\n",i,mat[i]?mat[i]-n:0);//printf("match=%d\n",res);return res;
}
int tag[N];
void dfs(int x){if(tag[x]) return;tag[x]=1;for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;tag[to]=1;assert(mat[to]);dfs(mat[to]);}
}signed main(){freopen("isolated.in","r",stdin);freopen("isolated.out","w",stdout);n=read();m=read();memset(fi,-1,sizeof(fi));cnt=-1;for(int i=1;i<=m;i++){int x=read(),y=read();f[x][y]=1;}for(int k=1;k<=n;k++){for(int i=1;i<=n;i++){for(int j=1;j<=n;j++) f[i][j]|=(f[i][k]&f[k][j]);}}for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(f[i][j]) addline(i,j+n),addline(j+n,i);//printf("(%d %d)\n",i,j);}}int ans=n-hangry();printf("%d\n",ans);//ans=n-hangry();//printf("%d\n",ans);for(int i=n+1;i<=n+n;i++) if(!mat[i]) dfs(i);for(int i=1;i<=n;i++){if(tag[i+n]&&!tag[i]) printf("1");else printf("0");}puts("");for(int i=1;i<=n;i++){memset(ban,0,sizeof(ban));int S(0);for(int x=1;x<=n;x++) if(i==x||f[x][i]||f[i][x]) ban[x]=ban[x+n]=1,++S;int res=n-S-hangry()+1;//printf("res=%d\n",res);if(res==ans) printf("1");else printf("0");}return 0;
}
/*
5 2
2 4
1 5
1 2
2 3
3 4
3 5
*/
总结
做题有的时候真的挺随缘的。
T1想到了一下就通了,想不到就是想不到。
还有T2这种,临门一脚就是射不出去,真心挺郁闷的。
还是太弱了,榜上那几个大佬总是屹立不倒的。
见到这种可离线互相独立的询问就应该多少想一想莫队。
还有,不能在一个思路吊死,思路打开。
明天加油吧!awa