【CSP-S 2019模拟】题解
T1:
傻逼题
显然对于一个,最大的为
用堆维护每一行的最大值
先用对数判大小再在取模的情况下计算答案
#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ob==ib)?EOF:*ib++;
}
#define gc getchar
inline int read(){
char ch=gc();
int res=0,f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
#define ll long long
#define re register
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cs const
#define bg begin
#define poly vector<int>
cs int mod=1e9+7;
inline int add(int a,int b){return (a+=b)>=mod?a-mod:a;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){return 1ll*a*b%mod;}
inline void Add(int &a,int b){(a+=b)>=mod?a-=mod:0;}
inline void Dec(int &a,int b){(a-=b)<0?a+=mod:0;}
inline void Mul(int &a,int b){a=1ll*a*b%mod;}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
inline void chemx(int &a,int b){a<b?a=b:0;}
inline void chemn(int &a,int b){a>b?a=b:0;}
cs int N=1000005;
pii ans[N];
int tot;
namespace Comb{
int fac[N],ifac[N];
inline void init(cs int len=N-5){
ifac[0]=fac[0]=1;
for(int i=1;i<=len;i++)fac[i]=mul(fac[i-1],i);
ifac[len]=Inv(fac[len]);
for(int i=len-1;i;i--)ifac[i]=mul(ifac[i+1],i+1);
}
inline int C(int n,int m){
return n<m?0:mul(fac[n],mul(ifac[m],ifac[n-m]));
}
inline int calc(){
int res=0;
for(int i=1;i<=tot;i++)
Add(res,C(ans[i].fi,ans[i].se));
return res;
}
}
#define ldb long double
struct node{
ldb val;int pos,tim;
node(ldb _v=0,int _p=0,int _t=0):val(_v),pos(_p),tim(_t){}
friend inline bool operator <(cs node &a,cs node &b){
return (a.val==b.val)?(a.pos==b.pos?a.tim<b.tim:a.pos<b.pos):a.val<b.val;
}
};
priority_queue<node> q;
int vis[N],n,k;
ldb v[N],fac[N];
inline void init(cs int len=N-5){
for(int i=1;i<=len;i++)v[i]=log2(i);
for(int i=1;i<=len;i++)fac[i]=fac[i-1]+v[i];
}
inline ldb C(int n,int m){
return n<m?0:(fac[n]-fac[m]-fac[n-m]);
}
int main(){
Comb::init(),init();
n=read(),k=read();
for(int i=0;i<=n;i++){
if(i&1)q.push(node(C(i,i/2),i,2));
else q.push(node(C(i,i/2),i,1));
vis[i]=i/2;
}
while(k>0){
node now=q.top();q.pop();
int t=min(k,now.tim);k-=t;
while(t--)ans[++tot]=pii(now.pos,vis[now.pos]);
vis[now.pos]--;
if(vis[now.pos]>=0)q.push(node(C(now.pos,vis[now.pos]),now.pos,2));
}
cout<<Comb::calc();
}
T2:
显然暴力是每次建出统计答案
考虑这个不好维护,用莫队做
先把整体的建出来
每次把一个串的权值加到上
由于对串分块复杂度会和串长有关
考虑把所有串拼起来分块
这样暴力删每个字符
复杂度就是对的了,每次判断上每个节点是否被加入/删除
用一个链表维护每个空段
但是链表只能直接删除和回退
所以要写回滚莫队
复杂度
#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ob==ib)?EOF:*ib++;
}
#define gc getchar
inline int read(){
char ch=gc();
int res=0,f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
#define ll long long
#define re register
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cs const
#define poly vector<int>
inline void chemx(int &a,int b){a<b?a=b:0;}
cs int N=300005;
int A,B,C,n,m,a[N],num;
int len[N],pos[N],vis[N];
int v[N],g[N],bel[N],L,blo,cnt,fir[N],bg[N],ed[N];
char s[N];
ll ans,anc[N],V;
inline ll S(int x){
return 1ll*x*(x+1)/2;
}
inline ll gcd(ll a,ll b){
return b?gcd(b,a%b):a;
}
struct opt{
int l,r,id;
friend inline bool operator <(cs opt &a,cs opt &b){
return bel[a.l]==bel[b.l]?a.r>b.r:a.l<b.l;
}
}p[N];
int pre[N],suf[N],top;
struct node{
int l,p,r;
node(int _l=0,int _p=0,int _r=0):l(_l),p(_p),r(_r){}
}stk[N];
inline void getback(){
while(top){
int l=stk[top].l,p=stk[top].p,r=stk[top].r;
ans-=S(r-l-1),ans+=S(p-l-1),ans+=S(r-p-1);
pre[r]=p,suf[l]=p,top--;
}
}
inline void delet(int p){
int l=pre[p],r=suf[p];
ans-=S(p-l-1)+S(r-p-1),ans+=S(r-l-1);
stk[++top]=node(l,p,r);
pre[r]=l,suf[l]=r;
}
inline void build(){
for(int i=1,last=0;i<=L+1;i++){
if(vis[i])suf[last]=i,pre[i]=last,ans+=S(i-last-1),last=i;
}
}
int dep[N],val[N],nxt[N][26],tot;
inline void insert(int id,int coef){
int p=0;coef*=v[id];
for(int i=bg[id];i<=ed[id];i++){
int c=a[i];
if(!nxt[p][c])nxt[p][c]=++tot,dep[tot]=dep[p]+1;
p=nxt[p][c];
int pre=(val[p]>0&&1ll*B*val[p]+1ll*A*dep[p]>=C);
val[p]+=coef;
int nxt=(val[p]>0&&1ll*B*val[p]+1ll*A*dep[p]>=C);
if(!pre&&nxt){vis[g[dep[p]]]++;}
if(pre&&!nxt){vis[g[dep[p]]]--;if(!vis[g[dep[p]]])delet(g[dep[p]]);}
}
}
signed main(){
n=read(),A=read(),B=read(),C=read();
for(int i=1;i<=n;i++)v[i]=read();
for(int i=1;i<=n;i++){
scanf("%s",s+1);
len[i]=strlen(s+1);
bg[i]=num+1;
for(int j=1;j<=len[i];j++)
a[++num]=s[j]-'a';
ed[i]=num;
chemx(L,len[i]);
}
for(int i=1;i<=L;i++)g[i]=read();
m=read();vis[L+1]=1;
for(int i=1;i<=m;i++)p[i].l=read(),p[i].r=read(),p[i].id=i;
blo=sqrt(num);
bel[1]=1;V=S(L);
for(int i=1,j=2;j<=n;j++){
bel[j]=bel[j-1];
if(ed[j]-bg[i]+1>blo)
bel[j]++,i=j;
}
cnt=bel[n];
sort(p+1,p+m+1);
for(int i=1;i<=n;i++)
if(!fir[bel[i]])fir[bel[i]]=i;
for(int i=1,j,pos=1;i<=cnt;i++){
ans=0;
for(j=fir[i];j<=n;j++)insert(j,1);
build();
for(j=n;pos<=m&&bel[p[pos].l]==i;pos++){
while(j>p[pos].r)insert(j,-1),j--;
top=0;
for(int k=fir[i];k<p[pos].l;k++)insert(k,-1);
anc[p[pos].id]=V-ans;
for(int k=fir[i];k<p[pos].l;k++)insert(k,1);
getback();
}
while(j>=fir[i])insert(j,-1),j--;
}
for(int i=1;i<=m;i++){
ll gg=gcd(V,anc[i]);
cout<<anc[i]/gg<<"/"<<V/gg<<'\n';
}
}
T3:
据说出题人用屁眼造数据
造一个半径为小数点后不知道多少位的圆,平方一下就没了的那种
于是咕咕咕