上午参与了一下,随缘开题,之后会补若干这场感兴趣的题。另外就是最近cf先不跟了,这周之后补补cf,未来可期。
文中代码均为不完全片段,建议配合代码模板食用。
目录
B.二进制
D.分配颜色
E.土地规划
F.CTF
G.希望
J.抽奖
Solution:
a的每个二进制位对应一棵线段树,开设10棵左右线段树,分别维护区间修改、区间查询即可。
时间复杂度:O(nlogn*loga)
Code:
int n,q;
struct segment
{
int val,col;
segment()
{
val=col=0;
}
}tr[20][N<<1];
inline void push_up(int now,int tag)
{
tr[tag][now].val=tr[tag][now<<1].val+tr[tag][now<<1|1].val;
}
inline void color(int now,int l,int r,int val,int tag)
{
tr[tag][now].val+=val*(r-l+1);
tr[tag][now].col+=val;
}
inline void push_down(int now,int l,int r,int tag)
{
int mid=(l+r)>>1;
color(lson,tr[tag][now].col,tag);
color(rson,tr[tag][now].col,tag);
tr[tag][now].col=0;
}
void upd(int now,int l,int r,int nl,int nr,int val,int tag)
{
if(nl<=l&&r<=nr)
{
color(now,l,r,val,tag);
return;
}
push_down(now,l,r,tag);
int mid=(l+r)>>1;
if(nl<=mid) upd(lson,nl,nr,val,tag);
if(mid>1;
int ans=0;
if(nl<=mid) ans+=qry(lson,nl,nr,tag);
if(mid>n>>q;
while(q--)
{
int opt,a,l,r,k;
cin>>opt>>a>>l>>r;
if(opt==1)
{
cin>>k;
int tmp=1;
while(a)
{
if(a&1)upd(1,1,n,l,r,k,tmp);
a>>=1;++tmp;
}
}
else
{
int ans=0,tmp=1;
while(a)
{
if(a&1)ans+=qry(1,1,n,l,r,tmp);
a>>=1;++tmp;
}
cout<
Solution:
组合计数,分析可知最后蓝色的方格即为被操作过奇数次的位置。
考虑最终有pi行,qi列被操作过奇数次的状态,该状态共有p*m+q*n-2*p*q个蓝色方格,若方格数等于t则可能对答案产生贡献。(pi,qi)状态共有C(n,pi)*C(m,qi)种情况。
易知如果p 因此答案ans=Sigma C(n,pi)*C(m,qi)*C(n+dp/2-1,dp/2)*C(m+dq/2-1,dq/2) O(n^2)预处理阶乘计算组合数即可(注意娇贵的模数)。 Code: Solution: 模拟几次操作过程可以发现,第i次操作的方格(xi,yi)满足xi+yi=2*i(沿着对角线),共操作i个方格。即第i次会操作(i,i)~(2i,0)的所有i个点,并判断是否染色。 同时对于方格(xi,yi),若(xi-1,yi-1)与(xi-2,yi)均已被染色,此时该方格则不会被染色。以上是对题目的解读。 若只考虑方格是否被染色,可以发现题目具有杨辉三角的性质(将每一对角线视为杨辉三角的一行)。进而对于每一个方格的染色情况,只需要判断在杨辉三角中该位置组合数C(n,k)的奇偶性即可。 性质:对于组合数C(n,k),n&k==k当且仅当C(n,k)为奇数。 对于每个被染色方格的颜色,只需要判断它在哪一次操作被染色即可。 时间复杂度:O(a*b)=O(a^2) Code: Solution: 从小到大枚举i,并在接下来的1<
Code: Solution: 题意可知两棵树之间的所有n!种连边方式均会被遍历到,求期望值。由于n!的值较大,这里考虑计算答案的式子应当可以把阶乘项消去。 易知A与B树之间连接成长为L的环,一定由A中某条长为La的链,与B中某条长为Lb的链首尾相接而成,其中La+Lb=L-2。考虑A中所有距离为La的点对(ia,ja)有cnta[La]个,B中距离为Lb的点对(ib,jb)有cntb[Lb]个。 对于某一种情况(ia,ja)与(ib,jb),当 因此,A中长为La的所有链与B中长为Lb所有链进行拼接的情况,对答案的贡献为2*(n-2)!*cnta[La]*cntb[Lb]。由1到m-3枚举所有合法La,Lb=m-2-La,累加即得到总方案数。由于最终答案会除以n!,因此可以将阶乘项消去,得到方案数最终除以n*(n-1)即可。 问题转化为如何求解树中长为k的点对数量,这里使用树形dp求解。记dp[i][j]为结点i所有子节点中距离为j的结点数,易知dp[i][0]=1,且dp[i][j]=sigma dp[son][j-1]。对于当前结点枚举其子节点并进行dfs,每次dfs某个son后更新cnt[k]+=sigma dp[i][j]*dp[son][k-j-1],最后可以统计出距离为k的所有点对。 时间复杂度:O(n*m) Code: Solution: 签到题。首先求出x颗原石的抽奖次数,并得到相应的星辉。然后循环使用星辉抽奖,扣除相应的星辉并添加得到的星辉,直到星辉数目不够抽奖为止。 Code: 候补int n,m,p,q,t;
int ans;
int C[N][N];
inline void pre(int n)
{
rep(i,0,n)C[i][0]=C[i][i]=1;
rep(i,1,n)rep(j,i+1,n)C[j][i]=(C[j-1][i-1]+C[j-1][i])%mod;
}
inline int func(int pi,int qi)
{
if(pi>p||qi>q)return 0;
int dp=p-pi,dq=q-qi;
if(dp%2==1||dq%2==1)return 0;
dp/=2,dq/=2;
int ans=1;
ans=C[n][pi]*C[m][qi]%mod;
ans=ans*C[n+dp-1][dp]%mod;
ans=ans*C[m+dq-1][dq]%mod;
return ans;
}
/*----------------------*/
inline void Main()
{
cin>>n>>m>>p>>q>>t;
pre(N-1);
rep(pi,0,n)rep(qi,0,m)
if(pi*m+qi*n-2*pi*qi==t)ans=(ans+func(pi,qi))%mod;
cout<
E.土地规划
int t,x,y,a,b;
inline bool che(int i,int j)
{
int n=(i+j)>>1;
int k=n*2-i;
return (n&k)==k;
}
/*----------------------*/
inline void Main()
{
cin>>t>>x>>y>>a>>b;
--t;
per(j,b+y-1,y)
{
rep(i,x,a+x-1)
if((i+j)&1||i
F.CTF
int t,ans;
/*----------------------*/
inline void Main()
{
cin>>t;
int now=0;
rep(i,1,30)
{
int max_rep=1<
G.希望
int n,m;
int hd[2][N],tot[2];
struct edge
{
int to,nxt;
edge()
{
to=nxt=0;
}
}ed[2][N<<1];
inline void add(int u,int v,int tag)
{
++tot[tag];
ed[tag][tot[tag]].to=v;
ed[tag][tot[tag]].nxt=hd[tag][u];
hd[tag][u]=tot[tag];
}
int dp[2][N][N],cnt[2][N];
void dfs(int now,int pre,int tag)
{
dp[tag][now][0]=1;
for(int i=hd[tag][now];i;i=ed[tag][i].nxt)
{
int next=ed[tag][i].to;
if(next==pre)continue;
dfs(next,now,tag);
rep(j,0,m-1)
{
rep(dis,j+1,m)cnt[tag][dis]+=dp[tag][now][j]*dp[tag][next][dis-j-1];
if(j>0)dp[tag][now][j]+=dp[tag][next][j-1];
}
}
}
/*----------------------*/
inline void Main()
{
cin>>n>>m;
rep(tag,0,1)rep(i,1,n-1)
{
int x,y;cin>>x>>y;
add(x,y,tag);add(y,x,tag);
}
dfs(1,0,0);dfs(1,0,1);
int res=0;
rep(d,1,m-3)res+=2*cnt[0][d]*cnt[1][m-d-2];
double ans=res;
ans/=(double)(n*(n-1));
cout<
J.抽奖
int x,y,ans;
/*----------------------*/
inline void Main()
{
cin>>x;
ans+=x/160;
y=(ans/10)*3;
while(y>=5)
{
int tmp=ans;
ans+=y/5;
y%=5;
y+=(ans/10-tmp/10)*3;
}
cout<