多校冲刺 NOIP 20211104 模拟 (22)
T1 迷之阶乘
签到题,由于我实在垃圾,不会用\(pow\)这种高级东西,并且以为不让开\(int128\)于是傻不拉几的把边界的表给打了出来
二分,复杂度\(Tlog(n)^2\)
#include<bits/stdc++.h>
#define ull unsiged long long
#define int long long
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
int n,l[21],rr[21];
struct node{int l,r;}p[21];
bool cmp(node a,node b){return a.l<b.l;}
inline int getnum(int x){int res=0;while(x){res++;x/=10;}return res;}
signed main()
{
freopen("factorial.in","r",stdin);
freopen("factorial.out","w",stdout);
int t=read();
rr[2]=1e9;rr[3]=1e6;rr[4]=40000;rr[5]=4000;
rr[6]=1e3;rr[7]=430;rr[8]=200;rr[9]=100;rr[10]=65;rr[11]=40;
rr[12]=29;rr[13]=20;rr[14]=13;rr[15]=10;rr[16]=6;rr[17]=4;
rr[18]=2;rr[19]=1;
while(t--)
{
n=read();
for(int i=20;i>=1;i--) p[i].l=p[i].r=-1;
if(n==1){puts("-1");continue;}
p[1].l=n;p[1].r=n-1;
for(int i=2;i<=19;i++)
{
int l=1,r=rr[i],mid;
int ans=-1;
while(l<=r)
{
mid=(l+r)>>1;int res=1; int num=0;
for(int j=mid+1;j<=mid+i;j++) num+=getnum(j)-1;
if(num>=18) {r=mid-1;continue;}
for(int j=mid+1;j<=mid+i;j++) res=res*j;
if(res>n) r=mid-1; else if(res<n) l=mid+1;
else {ans=mid;break;}
}
if(ans!=-1) p[i].l=ans+i,p[i].r=ans;
}
sort(p+1,p+1+19,cmp);int cnt=0;
for(int i=1;i<=19;i++) if(p[i].l!=-1) cnt++;
printf("%lld\n",cnt);
for(int i=1;i<=19;i++) if(p[i].l!=-1)
printf("%lld %lld\n",p[i].l,p[i].r);
}
}
T2 子集
特判断\(k=1\)的情况,然后分奇偶处理
设\(n/k\)为\(m\)
\(m\)为偶数的话显然都有解,瞎算就行了
考虑为奇数的情况,\(m=1\)显然无解
若\(k,m\)皆为奇数,可以先用前\(3k\)个数构成一个合法的方案,剩下的就是偶数的情况了
T3 混凝土粉末
比较弱,考场上值想到了主席树二分的\(qlog(n)^2\)的做法,结果跟\(qlog(n)^3\)和\(q\sqrt{n}log(n)\)一个分
正解的话就是以时间为下标开一棵线段树,然后扫描线维护一下就行了
#include<bits/stdc++.h>
#define ull unsiged long long
#define ll long long
#define lid id<<1
#define rid id<<1|1
using namespace std;
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int maxn=1e6+5;
ll sum[maxn*4];int n,m,ans[maxn];
struct node{int x,id;ll h;};bool vis[maxn];
vector<node>ins[maxn],que[maxn],del[maxn];
inline void update(int id,int l,int r,int pos,ll val)
{
sum[id]+=val;if(l==r)return;
int mid=(l+r)>>1;
if(pos<=mid) update(lid,l,mid,pos,val);
if(pos>mid) update(rid,mid+1,r,pos,val);
}
inline int query(int id,int l,int r,ll val)
{
if(l==r) return l; int mid=(l+r)>>1;
if(sum[lid]>=val) return query(lid,l,mid,val);
else return query(rid,mid+1,r,val-sum[lid]);
}
signed main()
{
freopen("concrete.in","r",stdin);
freopen("concrete.out","w",stdout);
n=read(); m=read();
for(int i=1;i<=m;i++)
{
int type=read();
if(type==1)
{
int l=read(),r=read(),h=read();
ins[l].push_back((node){l,i,h});
del[r].push_back((node){r,i,h});
}
else
{
int x=read();ll y=read();vis[i]=1;
que[x].push_back((node){x,i,y});
}
}
for(int i=1;i<=n;i++)
{
for(auto y:ins[i]) update(1,1,m,y.id,y.h);
for(auto y:que[i])
{
if(sum[1]<y.h) continue;
int x=query(1,1,m,y.h);
if(x<=y.id) ans[y.id]=x;
}
for(auto y:del[i]) update(1,1,m,y.id,-y.h);
}
for(int i=1;i<=m;i++) if(vis[i]) printf("%d\n",ans[i]);
}
T4 排水系统
先按照没有删除边跑以此,再根据期望的线性性再做一次,算出其他的部分
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pii pair<int,int>
#define int long long
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int maxn=5e5+5,mod=998244353;
int n,m,r,k,sum,inv,ans[maxn],h[maxn],w[maxn],du[maxn],normal[maxn],gai[maxn],cnt,chu[maxn],tmp[maxn],iv[maxn];
vector<pii>p[maxn];vector<int>pp[maxn];queue<int>q;
struct bb{int a,b,v;}edge[maxn];
inline int ksm(int x,int y){int res=1;x=x%mod;for(;y;y>>=1){if(y&1)res=res*x%mod;x=x*x%mod;}return res;}
bool bo[maxn];int pr[maxn];
inline void shai()
{
iv[1]=1;for(int i=2;i<=n;i++)
{if(!bo[i]){iv[i]=ksm(i,mod-2);pr[++cnt]=i;}for(int j=1;j<=cnt&&i*pr[j]<=n;j++)
{bo[i*pr[j]]=1;iv[i*pr[j]]=iv[i]*iv[pr[j]]%mod;if(!(i%pr[j])) break;}}
}
signed main()
{
freopen("water.in","r",stdin);
freopen("water.out","w",stdout);
n=read();m=read();r=read();k=read();
for(int i=1;i<=m;++i)w[i]=1;shai();
for(int i=1;i<=k;++i)
{
int a,b,v;
scanf("%lld%lld%lld",&a,&b,&v);
p[a].push_back(mp(b,v));
++du[b]; sum+=v;
edge[i]=(bb){a,b,v};
}
inv=ksm(sum,mod-2);
for(int i=1;i<=m;++i)q.push(i),w[i]=1;
memcpy(tmp,du,sizeof(tmp));
while(!q.empty())
{
int x=q.front();q.pop(); if(!p[x].size())continue;
int inv1=iv[p[x].size()],inv2=iv[p[x].size()-1];
for(auto i:p[x])
{
int v=i.fi,val=i.se;--du[v];
chu[x]=(chu[x]+(w[x]*(inv2-inv1+mod)%mod)*val%mod*inv%mod*p[x].size()%mod)%mod;
chu[v]=(chu[v]-w[x]*inv1%mod*val%mod*inv%mod-(w[x]*(inv2-inv1+mod)%mod)*val%mod*inv%mod+mod*2)%mod;
w[v]=(w[v]+w[x]*inv1)%mod; if(!du[v])q.push(v);
}
}
memcpy(du,tmp,sizeof(du));
for(int i=1;i<=m;++i)chu[i]++;
for(int i=1;i<=m;++i)q.push(i),w[i]=1;
while(!q.empty())
{
int x=q.front();q.pop();
int inv1=iv[p[x].size()];
for(auto i:p[x])
{
int v=i.fi,val=i.se;--du[v];
if(!du[v])q.push(v);
chu[v]=(chu[v]+chu[x]*inv1)%mod;
}
}
for(int i=n-r+1;i<=n;++i) printf("%lld ",chu[i]);
}