4.13省选模拟
这是博客园的第一百篇随笔\(!\)
不说别的,感觉代码能力真的提升很大,认真敲代码真的很畅快,好嘛\(!\)
一个原来的信竞生送来了一个省选祝福吧,感觉一句话说的很好
能走到现在,你们早已是赢家,抛去世界的一切,这一次,是为自己而战
\(T1\)
考场上一眼看出来正解,半平面交不会写,就造了一个假的半平面交。。(复杂度不对)
考场暴力代码(有一些细节也没处理好,考场上写了\(240+\))
#include
#define int long long
#define MAXN 200005
#define INF 1e30
using namespace std;
int sta[MAXN],son[MAXN],top1[MAXN],zx[MAXN][20],f[MAXN],top;
int head[MAXN],nxt[MAXN],to[MAXN],tot;
int n,m,cnt,siz[MAXN],dep[MAXN];
struct node
{
int a,s,id;
}poz[MAXN];
struct LINE
{
int k,st,ed,id,js,qs;
}Line[MAXN];
void add(int u,int v)
{
tot++;
to[tot]=v;
nxt[tot]=head[u];
head[u]=tot;
}
bool cmp(node x,node y)
{
if(x.a!=y.a) return x.amaxn)
{
maxn=siz[y];
son[now]=y;
}
}
}
void dfs_top(int now,int topn)
{
top1[now]=topn;
if(!son[now]) return ;
dfs_top(son[now],topn);
for(int i=head[now];i;i=nxt[i])
{
int y=to[i];
if(top1[y]) continue;
dfs_top(y,y);
}
}
int LCA(int x,int y)
{
while(top1[x]!=top1[y])
{
if(dep[top1[x]]dep[y]) swap(x,y);
return x;
}
int LEN(int x,int y)
{
return dep[x]+dep[y]-2*dep[LCA(x,y)];
}
int Find(int now,int dp)
{
for(int i=18;i>=0;i--)
{
if((dp>>i)&1) now=zx[now][i];
}
return now;
}
//注意编号顺序
signed main()
{
freopen("ant.in","r",stdin);
freopen("ckant.out","w",stdout);
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%lld",&poz[i].s);
poz[i].id=i;
}
for(int i=1;i<=n;i++)
{
scanf("%lld",&poz[i].a);
}
// for(int i=1;i<=n;i++)
// {
// poz[i].s+=poz[i].a;
// }
sort(poz+1,poz+1+n,cmp);
int top=0;
for(int i=1;i<=n;i++)
{
while(top&&poz[sta[top]].s<=poz[i].s) top--;
sta[++top]=i;
}
// for(int i=1;i<=top;i++)
// {
// cout<<"id: "<poz[sta[i]].id)
{
x++;
}
}
if(x=poz[sta[xz]].s+x*poz[sta[xz]].a)
{
jd=x;
xz=i;
}
// cout<<"jd: "<MidLen&&TimLen>1;
if(Line[mid].ed>=T-1)
{
ans=mid;
r=mid-1;
}
else
{
l=mid+1;
}
}
// cout<<"mid: "<MidLen&&TimLen
考后重写了一遍半平面交,改了改就过了
#include
#define int long long
#define MAXN 200005
#define INF 1e30
using namespace std;
int sta[MAXN],son[MAXN],top1[MAXN],zx[MAXN][20],f[MAXN],top;
int head[MAXN],nxt[MAXN],to[MAXN],tot;
int n,m,siz[MAXN],dep[MAXN];
struct node
{
int k,b,id;
}poz[MAXN],T[MAXN];
struct line
{
int st,ed,id,js,qs;
}Line[MAXN];
bool cmp(node a,node b)
{
if(a.k!=b.k) return a.kb.b;
return a.id>b.id;
}
int Get(node l1,node l2)
{
int x=ceil((l2.b-l1.b)*1.0/(l1.k-l2.k)*1.0);
if(l1.k*x+l1.b==l2.k*x+l2.b)
{
if(l1.id>l2.id) x++;
}
return x;
}
void add(int u,int v)
{
tot++;
to[tot]=v;
nxt[tot]=head[u];
head[u]=tot;
}
void dfs_pre(int now,int fa)
{
zx[now][0]=fa;
for(int i=1;i<=18;i++)
{
zx[now][i]=zx[zx[now][i-1]][i-1];
}
int maxn=-1;
dep[now]=dep[fa]+1;
siz[now]=1;
f[now]=fa;
for(int i=head[now];i;i=nxt[i])
{
int y=to[i];
if(y==fa) continue;
dfs_pre(y,now);
siz[now]+=siz[y];
if(siz[y]>maxn)
{
maxn=siz[y];
son[now]=y;
}
}
}
void dfs_top(int now,int topn)
{
top1[now]=topn;
if(!son[now]) return ;
dfs_top(son[now],topn);
for(int i=head[now];i;i=nxt[i])
{
int y=to[i];
if(top1[y]) continue;
dfs_top(y,y);
}
}
int LCA(int x,int y)
{
while(top1[x]!=top1[y])
{
if(dep[top1[x]]dep[y]) swap(x,y);
return x;
}
int LEN(int x,int y)
{
return dep[x]+dep[y]-2*dep[LCA(x,y)];
}
int Find(int now,int dp)
{
for(int i=18;i>=0;i--)
{
if((dp>>i)&1) now=zx[now][i];
}
return now;
}
signed main()
{
freopen("ant.in","r",stdin);
freopen("ant.out","w",stdout);
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%lld",&poz[i].b);
poz[i].id=i;
}
for(int i=1;i<=n;i++)
{
scanf("%lld",&poz[i].k);
}
sort(poz+1,poz+1+n,cmp);
T[top=1]=poz[1];
for(int i=2;i<=n;i++)
{
if(poz[i].k==poz[i-1].k) continue;
while(top>1&&(Get(T[top-1],poz[i])T[top].k*Get(T[top-1],poz[i])+T[top].b&&Get(T[top-1],poz[i])==Get(T[top-1],T[top])))) top--;
T[++top]=poz[i];
}
Line[0].ed=-1;
for(int i=1;i<=top;i++)
{
Line[i].id=T[i].id;
Line[i].st=Line[i-1].ed+1;
if(i!=top) Line[i].ed=Get(T[i],T[i+1])-1;
}
Line[top].ed=INF;
// for(int i=1;i<=top;i++)
// {
// cout<MidLen&&TimLen>1;
if(Line[mid].ed>=T-1)
{
ans=mid;
r=mid-1;
}
else
{
l=mid+1;
}
}
// cout<<"mid: "<MidLen&&TimLen
\(T2\)
大力插头\(dp\)即可
源自题解.......
#include
#define mod 1000000007
using namespace std;
const int x5[10]={1,5,25,125,625,3125,15625,78125};
int v,past,now;
int f[2][480000],n,m,k,s[100][10],x,y,all;
int b[480000][9];
void out()
{
for (int k=0;k
\(T3\)
计数题
如果把各种知识放在一起考虑,那么很麻烦,我们可以考虑一个一个知识去算,然后最后进行一下容斥操作
\(f(k)\)表示前\(k\)道题会做,后\(n-k\)道题不一定的方案数
\(g(k)\)表示前\(k\)道题会做,后\(n-k\)道题不会做的方案数
比较显然,\(f(k)\)包含\(g(k),\)我们需要把\(g(k)\)容斥出来
还是较为套路的二项式反演
\(f(k)=\sum C(j,k) g(j)\)
\(g(k)=\sum (-1)^{j-k} f(j)\)
我们考虑求\(f(x)\)可以把各种知识分开考虑,最后乘起来
我一直再想,这个会不会出现,前面符合要求,后面不符合要求的情况
其实我们每一步都是保证前\(n-k\)个,可以符合条件的方案,我一开始以为最后还要交换顺序之类的
就想的过于麻烦了,然后最后大概就是枚举\(Q\)每一个知识点的实力,最后相乘就好了
至于为什么二项式反演,我们强制让后面都严格大于不可以吗\(?\)
考虑最后他要会做这道题,那么就是说,我们总的中位数要满足条件
但是又说,我们这个即使前\(k\)个这个知识点会做,后面知识点的也不一定满足,这就是我们二项式容斥的必要我们最后\(f(k)\)表示的是全部知识点的情况
考虑每一种知识的时候,我们可以枚举\(Q\)的水平,假设为\(x,\)我们有一个\(a\)的范围使得既满足前\(n-k\)可做,后面的可能不可做,但是这道题会做...(有点混乱)
我们让\((n+1)/2<=a+k<=n\)
最后保留\(x,\)求出多项式系数,然后把多项式乘起来就好了
#include
#define mod 1000000007
#define int long long
#define maxn 102
using namespace std;
int C[105][105];
int sigma[105][105];
int n,m,k,u[105],p[105][105];
int ji;
int sqr(int x) {return (x*x)%mod;}
int qming(int a,int b)
{
if (!b) return 1;
if (b&1) return (sqr(qming(a,b>>1))*a)%mod;
return sqr(qming(a,b>>1));
}
void initC()
{
C[0][0]=1;
C[1][0]=C[1][1]=1;
for (int i=2;i<=maxn;i++)
{
C[i][0]=C[i][i]=1;
for (int j=1;j