高一上十一月中旬日记

11.11

闲话

  • 因为后天高二的要信息学考,所以今天的杂题选讲改成了模拟赛。打模拟赛前尝试和 \(field\) 交涉今天能不能不打模拟赛, \(field\) 说不行,因为昨天我们已经打“欢乐”赛了。
  • 上午 \(7:30 \sim 12:00\) 打学校 \(OJ\) 的模拟赛,教练直接搬的 【MX-S5】梦熊 NOIP 2024 模拟赛 1(同步赛)
  • 下午放 \(huge\) 的每日一歌《泡沫》,而且 \(field\) 让我们都要唱,于是楼道里准备艺术学考的高三的就听着我们“激情”唱歌了。上午的模拟赛 \(T1,T2,T3\) 线下讲解, \(T4\) 听的是直播回放。
  • 详见 2024 NOIP 游记 11.11
  • 吃完晚饭后 \(field\) 说因为明天高一的要考期中,所以让我们教室桌子的抽屉里有东西的回去收拾东西。

做题纪要

CF1967D Long Way to be Non-decreasing

luogu P11267 【MX-S5-T1】王国边缘

luogu P11268 【MX-S5-T2】买东西题

P484. 对称旅行者

CF2023D Many Games

[ABC218H] Red and Blue Lamps

  • 不妨钦定初始时所有灯的颜色都为红色,需要将 \(\min(r,n-r) \le \frac{n}{2}\) 盏灯变为蓝色。

  • 将第 \(i\) 盏灯变为蓝色的报酬为 \(a_{i-1}+a_{i}\) ,然后反悔贪心选不相邻的即可。

    点击查看代码
    ll a[200010],b[200010],vis[200010],pre[200010],suf[200010];
    priority_queue<pair<ll,ll> >q;
    int main()
    {
    // #define Issac
    #ifdef Issac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	ll n,r,pos,ans=0,i;
    	cin>>n>>r;
    	r=min(r,n-r);
    	for(i=1;i<=n;i++)
    	{
    		cin>>a[i];
    		b[i]=a[i-1]+a[i];
    		pre[i]=i-1;
    		suf[i]=i+1;
    		q.push(make_pair(b[i],i));
    	}
    	b[0]=b[n+1]=-0x3f3f3f3f;
    	for(i=1;i<=r;i++)
    	{
    		while(q.empty()==0&&vis[q.top().second]==1)
    		{
    			q.pop();
    		}
    		if(q.empty()==0)
    		{
    			ans+=q.top().first;
    			pos=q.top().second;
    			q.pop();
    			vis[pre[pos]]=vis[suf[pos]]=1;
    			b[pos]=b[pre[pos]]+b[suf[pos]]-b[pos];
    			q.push(make_pair(b[pos],pos));
    			pre[pos]=pre[pre[pos]];
    			suf[pos]=suf[suf[pos]];
    			pre[suf[pos]]=suf[pre[pos]]=pos;
    		}
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    

11.12

闲话

  • 上午 \(7:30 \sim 12:00\) 打 accoders NOI 的模拟赛。
  • 下午高二的有体育课, \(miaomiao\) 突然进来问高一的有没有也想下去 上体育课的,他能带我们跟着高二的一起去,从开学到现在一节体育课都没上过怎么行,遂拉着我们一起去上体育课了,并拿上了机房的四个乒乓球拍和三个乒乓球。去操场的路上,从教学楼经过发现他们的期中考试正在考英语。到操场后 \(miaomiao\) 让我们跟着高二的一起去上课就行了,过了一会儿 \(feifei\) 拿着机房的篮球下来找我们了。 \(miaomiao\) 说让我们等下课的时候就回去,然后我们就开始打乒乓球了(菜鸡互啄,只要能接住球就行,不管在不在乒乓球台上),期间跟着高二体测的跑 \(1km\) 但只跑了一圈就虚了。回到机房后听多校的讲题。

做题纪要

CF2025E Card Game

CF432D Prefixes and Suffixes

P489. 送信卒

luogu P10475 [USACO03FALL] Milking Grid(数据加强版)

  • 哈希压缩每一行和每一列,然后 \(KMP\) 求出最小循环节长度相乘即可。

    点击查看代码
    const ll mod=1000000007,base=13331;
    int a[100010],b[100010],nxt[100010];
    char c[100010][75],cc[75][10010];
    int sx_hash(char s[],int len)
    {
    	int ans=0;
    	for(int i=1;i<=len;i++)
    	{
    		ans=(ans*base%mod+s[i])%mod;
    	}
    	return ans;
    }
    int kmp(int n,int s[])
    {
    	for(int i=2,j=nxt[1]=0;i<=n;i++)
    	{
    		while(j>=1&&s[i]!=s[j+1])
    		{
    			j=nxt[j];
    		}
    		j+=(s[i]==s[j+1]);
    		nxt[i]=j;
    	}
    	return n-nxt[n];
    }	
    int main()
    {
    // #define Issac
    #ifdef Issac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	int n,m,i,j;
    	cin>>n>>m;
    	for(i=1;i<=n;i++)
    	{
    		for(j=1;j<=m;j++)
    		{
    			cin>>c[i][j];
    			cc[j][i]=c[i][j];
    		}
    		a[i]=sx_hash(c[i],m);
    	}
    	for(i=1;i<=m;i++)
    	{
    		b[i]=sx_hash(cc[i],n);
    	}
    	cout<<kmp(n,a)*kmp(m,b)<<endl;
    	return 0;
    }
    

P490. 共轭树图

11.13

  • 起床后发现下雨了,遂直接来机房了。到了之后先看了会儿百度新闻,当时 \(miaomiao\) 过来转悠时就站在我后面但他没管。早读时 \(miaomiao\) 说都敲了一天的代码了,让我们换换口味。
  • 上午 \(miaomiao\) 说他把机房外面桌子搬到了“五楼半”(五、六楼楼梯中间),寓意“步步高升”;今天没有模拟赛,让我们好好把前几天的题改一下。
  • 高二的去学考了。@SHLKST 因为一些原因需要回 \(HS\) 考, \(huge\) 让他到 \(HS\) 后联系的信息老师貌似是我初三原班主任。
  • 晚上 \(miaomiao\) 突然给我们下发了梦熊联盟 \(OJ\) 的账号,用户名是分发的,故用户名和邮箱不能改,只能改密码和绑定手机(不用输入原密码就能改),希望后面账号不要回收。被分到了 NOI-MRA-5638 。明天多校组织的模拟赛在上面打。

闲话

做题纪要

P491. 摸鱼军训

P492. 神奇园艺师

CF703D Mishka and Interesting sum

  • 莫队,略带卡常,加个超级快读。

  • 加入一个数时若并非第一次出现,则无脑异或进行消去/添加;删除这个数时若还有剩下的数,也异或进行消去/添加。

    点击查看代码
    namespace IO{
    	#ifdef LOCAL
    	FILE*Fin(fopen("test.in","r")),*Fout(fopen("test.out","w"));
    	#else
    	FILE*Fin(stdin),*Fout(stdout);
    	#endif
    	class qistream{static const size_t SIZE=1<<16,BLOCK=64;FILE*fp;char buf[SIZE];int p;public:qistream(FILE*_fp=stdin):fp(_fp),p(0){fread(buf+p,1,SIZE-p,fp);}void flush(){memmove(buf,buf+p,SIZE-p),fread(buf+SIZE-p,1,p,fp),p=0;}qistream&operator>>(char&x){x=getch();while(isspace(x))x=getch();return*this;}template<class T>qistream&operator>>(T&x){x=0;p+BLOCK>=SIZE?flush():void();bool flag=false;for(;!isdigit(buf[p]);++p)flag=buf[p]=='-';for(;isdigit(buf[p]);++p)x=x*10+buf[p]-'0';x=flag?-x:x;return*this;}char getch(){p+BLOCK>=SIZE?flush():void();return buf[p++];}qistream&operator>>(char*str){char ch=getch();while(ch<=' ')ch=getch();int i=0;for(;ch>' ';++i,ch=getch())str[i]=ch;str[i]='\0';return*this;}}qcin(Fin);
    	class qostream{static const size_t SIZE=1<<16,BLOCK=64;FILE*fp;char buf[SIZE];int p;public:qostream(FILE*_fp=stdout):fp(_fp),p(0){}~qostream(){fwrite(buf,1,p,fp);}void flush(){fwrite(buf,1,p,fp),p=0;}template<class T>qostream&operator<<(T x){int len=0;p+BLOCK>=SIZE?flush():void();x<0?(x=-x,buf[p++]='-'):0;do buf[p+len]=x%10+'0',x/=10,++len;while(x);for(int i=0,j=len-1;i<j;++i,--j)std::swap(buf[p+i],buf[p+j]);p+=len;return*this;}qostream&operator<<(char x){putch(x);return*this;}void putch(char ch){p+BLOCK>=SIZE?flush():void();buf[p++]=ch;}qostream&operator<<(char*str){for(int i=0;str[i];++i)putch(str[i]);return*this;}qostream&operator<<(const char*s){for(int i=0;s[i];++i)putch(s[i]);return*this;}}qcout(Fout);
    }
    #define cin IO::qcin
    #define cout IO::qcout
    int a[1000010],b[1000010],c[1000010],ans[1000010],L[1000010],R[1000010],pos[1000010],cnt[1000010],klen,ksum;
    struct ask
    {
    	int l,r,id;
    }q[1000010];
    bool q_cmp(ask a,ask b)
    {
    	return (pos[a.l]==pos[b.l])?((pos[a.l]%2==1)?(a.r<b.r):(a.r>b.r)):(a.l<b.l);
    }
    void init(int n,int m)
    {
    	klen=n/sqrt(m)+1;
    	ksum=n/klen;
    	for(int i=1;i<=ksum;i++)
    	{
    		L[i]=R[i-1]+1;
    		R[i]=R[i-1]+klen;
    	}
    	if(R[ksum]<n)
    	{
    		ksum++;
    		L[ksum]=R[ksum-1]+1;
    		R[ksum]=n;
    	}
    	for(int i=1;i<=ksum;i++)
    	{
    		for(int j=L[i];j<=R[i];j++)
    		{
    			pos[j]=i;
    		}
    	}
    }
    void add(int x,int &sum)
    {
    	cnt[a[x]]++;
    	sum^=(cnt[a[x]]>=2)*c[x];
    }
    void del(int x,int &sum)
    {
    	sum^=(cnt[a[x]]>=2)*c[x];
    	cnt[a[x]]--;
    }
    int main()
    {
    // #define Issac
    #ifdef Issac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	int n,m,l=1,r=0,sum=0,i;
    	cin>>n;
    	for(i=1;i<=n;i++)
    	{
    		cin>>a[i];
    		b[i]=c[i]=a[i];
    	}
    	sort(b+1,b+1+n);
    	b[0]=unique(b+1,b+1+n)-(b+1);
    	for(i=1;i<=n;i++)
    	{
    		a[i]=lower_bound(b+1,b+1+b[0],a[i])-b;
    	}
    	cin>>m;
    	init(n,m);
    	for(i=1;i<=m;i++)
    	{
    		cin>>q[i].l>>q[i].r;
    		q[i].id=i;
    	}
    	sort(q+1,q+1+m,q_cmp);
    	for(i=1;i<=m;i++)
    	{
    		while(l>q[i].l)
    		{
    			l--;
    			add(l,sum);
    		}
    		while(r<q[i].r)
    		{
    			r++;
    			add(r,sum);
    		}
    		while(l<q[i].l)
    		{
    			del(l,sum);
    			l++;
    		}
    		while(r>q[i].r)
    		{
    			del(r,sum);
    			r--;
    		}
    		ans[q[i].id]=sum;
    	}
    	for(i=1;i<=m;i++)
    	{
    		cout<<ans[i]<<endl;
    	}
    	return 0;
    }
    

luogu P5268 [SNOI2017] 一个简单的询问

  • 等价于查询 \(\begin{aligned} &\sum\limits_{x} (\operatorname{get}(1,r_{1},x)-\operatorname{get}(1,l_{1}-1,x))(\operatorname{get}(1,r_{2},x)-\operatorname{get}(1,l_{2}-1,x)) \\ &=\sum\limits_{x} \operatorname{get}(1,r_{1},x) \operatorname{get}(1,r_{2},x)-\operatorname{get}(1,r_{1},x)\operatorname{get}(1,l_{2}-1,x)-\operatorname{get}(1,l_{1}-1,x) \operatorname{get}(1,r_{2},x)+\operatorname{get}(1,l_{1}-1,x)\operatorname{get}(1,l_{2}-1,x) \end{aligned}\)

  • 考虑将其拆成 \(\begin{cases} \sum\limits_{x} \operatorname{get}(1,r_{1},x) \operatorname{get}(1,r_{2},x) \\ -\sum\limits_{x} \operatorname{get}(1,r_{1},x) \operatorname{get}(1,l_{2}-1,x) \\ -\sum\limits_{x} \operatorname{get}(1,l_{1}-1,x) \operatorname{get}(1,r_{2},x) \\ \sum\limits_{x} \operatorname{get}(1,l_{1}-1,x) \operatorname{get}(1,l_{2}-1,x) \end{cases}\) 四组询问。

  • 考虑莫队移动左右指针的实质是扩展相邻区间的答案,而本题中只维护询问的右端点即可,两个 \(\operatorname{get}\) 分别开个桶维护即可。

    点击查看代码
    ll a[50010],ans[50010],L[50010],R[50010],pos[50010],cntl[50010],cntr[50010],klen,ksum,cnt;
    struct ask
    {
    	ll l,r,id,pd;
    }q[200010];
    bool q_cmp(ask a,ask b)
    {
    	return (pos[a.l]==pos[b.l])?(a.r<b.r):(a.l<b.l);
    }
    void init(ll n,ll m)
    {
    	klen=n/sqrt(m)+1;
    	ksum=n/klen;
    	for(int i=1;i<=ksum;i++)
    	{
    		L[i]=R[i-1]+1;
    		R[i]=R[i-1]+klen;
    	}
    	if(R[ksum]<n)
    	{
    		ksum++;
    		L[ksum]=R[ksum-1]+1;
    		R[ksum]=n;
    	}
    	for(int i=1;i<=ksum;i++)
    	{
    		for(int j=L[i];j<=R[i];j++)
    		{
    			pos[j]=i;
    		}
    	}
    }
    void add(ll l,ll r,ll id,ll pd)
    {
    	cnt++;
    	q[cnt].l=l;
    	q[cnt].r=r;
    	q[cnt].id=id;
    	q[cnt].pd=pd;
    }
    void addl(ll x,ll &sum)
    {
    	cntl[a[x]]++;
    	sum+=cntr[a[x]];
    }
    void addr(ll x,ll &sum)
    {
    	cntr[a[x]]++;
    	sum+=cntl[a[x]];
    }
    void dell(ll x,ll &sum)
    {
    	cntl[a[x]]--;
    	sum-=cntr[a[x]];
    }
    void delr(ll x,ll &sum)
    {
    	cntr[a[x]]--;
    	sum-=cntl[a[x]];
    }
    int main()
    {
    // #define Issac
    #ifdef Issac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	ll n,m,l=0,r=0,sum=0,l1,l2,r1,r2,i;
    	cin>>n;
    	for(i=1;i<=n;i++)
    	{
    		cin>>a[i];
    	}
    	cin>>m;
    	for(i=1;i<=m;i++)
    	{
    		cin>>l1>>r1>>l2>>r2;
    		add(r1,r2,i,1);
    		add(r1,l2-1,i,-1);
    		add(l1-1,r2,i,-1);
    		add(l1-1,l2-1,i,1);
    	}
    	init(n,cnt);
    	sort(q+1,q+1+cnt,q_cmp);
    	for(i=1;i<=cnt;i++)
    	{
    		while(l<q[i].l)
    		{
    			l++;
    			addl(l,sum);
    		}
    		while(l>q[i].l)
    		{
    			dell(l,sum);	
    			l--;
    		}	
    		while(r<q[i].r)
    		{
    			r++;
    			addr(r,sum);
    		}
    		while(r>q[i].r)
    		{
    			delr(r,sum);
    			r--;
    		}
    		ans[q[i].id]+=q[i].pd*sum;
    	}
    	for(i=1;i<=m;i++)
    	{
    		cout<<ans[i]<<endl;
    	}
    	return 0;
    }
    

11.14

闲话

  • 早起后发现地面还湿着,遂直接去机房了。 \(huge\) 让我们“激情早读”。
  • 上午 \(7:30 \sim 12:00\) 打梦熊联盟的模拟赛。临开始前 \(huge\) 以为我们知道比赛密码就一直没说,直到有人来问密码他才说了下密码。
  • 下午讲题。
  • 晚上 \(miaomiao\) 来转悠时强调做题要靠自己,一味地靠别人是做不下去题的。
  • 临下课时 \(huge\) 进来强调了下上厕所的问题,刚才开会的时候说西扩那边已经落实了 \(21:20 \sim 21:40\) 不允许上厕所,否则需要在教室外的楼道里站着,然后就出现了一到 \(21:30\) 的时候楼道里就站了一排人,等 \(21:40\) 后就直接走了,我们差不多也落实这个制度,临下课前不允许去厕所(之前只规定 \(7:30 \sim 8:30\) 不允许去厕所);他自我感觉是个很“固执”的人,也知道由很多人对他的某些规定表示不满,但"你们现在的一些想法和建议应该是改不了我,那就改变自己,尝试着适应一下";就剩下这半个多月了,让我们再忍忍(搞不懂他这话是什么意思,想退役的早就在考 \(CSP\) 前后退役了,怎么会有 \(NOIP\) 集训到一半再退役的呢);他感觉机房的管理相比 \(whk\) 管理已经宽松许多,他现在有点担心我们退役后会适应不了 \(whk\) 严格的管理,万一再分着个不太好的班主任让自己整厌学了、不想上课了,那就不太好了,让我们提前适应一下;手表的整点响铃建议关掉,可能会影响到一些人的思考,我们也的确需要一些时间独立进行深度思考。

做题纪要

CF633H Fibonacci-ish II

  • 考虑莫队,先对原序列进行离散化。

  • 考虑新加入一个数时在权值线段树将后面的数的斐波那契矩阵都乘上一个转移矩阵的系数来表示斐波那契下标加一,删除时将后面的数的斐波那契矩阵都除上一个转移矩阵的系数来表示斐波那契下标减一。

  • 对于常见写法 \(\begin{bmatrix} Fib_{n} & Fib_{n+1} \\ 0 & 0 \end{bmatrix}=\begin{bmatrix} 0 & 1 \\ 0 & 0 \end{bmatrix} \times \begin{bmatrix} 0 & 1 \\ 1 & 1 \end{bmatrix}^{n}\) ,我们发现 \(\begin{bmatrix} 0 & 1 \\ 0 & 0 \end{bmatrix}\) 没有逆矩阵,只能另行他法尝试删去其中的 \(0\)

  • 另一种写法是 \(\begin{bmatrix} Fib_{n+1} & Fib_{n} \\ Fib_{n} & Fib_{n-1} \end{bmatrix}=\begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix} \times \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}^{n}\) ,而 \(\begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix}\) 的逆矩阵是它本身, \(\begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix}\) 的逆矩阵是 \(\begin{bmatrix} 0 & 1 \\ 1 &-1 \end{bmatrix}\) 。这样就解决了乘/除一个系数的问题。

  • 略带卡常。需要取模优化和预处理斐波那契及其逆矩阵。

    点击查看代码
    int a[30010],b[30010],c[30010],pos[30010],L[30010],R[30010],ans[30010],cnt[30010],klen,ksum,p;
    struct ask
    {
    	int l,r,id;
    }q[30010];
    bool q_cmp(ask a,ask b)
    {
    	return (pos[a.l]==pos[b.l])?((pos[a.l]%2==1)?(a.r<b.r):(a.r>b.r)):(a.l<b.l);
    }
    struct Matrix
    {
    	int ma[4];
    	Matrix()
    	{
    		memset(ma,0,sizeof(ma));
    	}
    	Matrix operator + (const Matrix &another)
    	{
    		Matrix ans;
    		ans.ma[0]=(ma[0]+another.ma[0])%p;
    		ans.ma[1]=(ma[1]+another.ma[1])%p;
    		ans.ma[2]=(ma[2]+another.ma[2])%p;
    		ans.ma[3]=(ma[3]+another.ma[3])%p;
    		return ans;
    	}
    	Matrix operator * (const Matrix &another)
    	{
    		Matrix ans;
    		ans.ma[0]=(ma[0]*another.ma[0]+ma[1]*another.ma[2])%p;
    		ans.ma[1]=(ma[0]*another.ma[1]+ma[1]*another.ma[3])%p;
    		ans.ma[2]=(ma[2]*another.ma[0]+ma[3]*another.ma[2])%p;
    		ans.ma[3]=(ma[2]*another.ma[1]+ma[3]*another.ma[3])%p;
    		return ans;
    	}
    	Matrix operator * (const int &another)
    	{
    		Matrix ans;
    		ans.ma[0]=ma[0]*another;
    		ans.ma[1]=ma[1]*another;
    		ans.ma[2]=ma[2]*another;
    		ans.ma[3]=ma[3]*another;
    		return ans;
    	}
    }Base,invBase,Fib[30010],invFib[30010];
    struct SMT
    {
    	struct SegmentTree
    	{
    		int val,lazy;
    		Matrix sum;
    	}tree[120010];
    	#define lson(rt) (rt<<1)
    	#define rson(rt) (rt<<1|1)
    	void pushup(int rt)
    	{
    		tree[rt].sum=(tree[lson(rt)].sum*tree[lson(rt)].val)+(tree[rson(rt)].sum*tree[rson(rt)].val);
    	}
    	void build(int rt,int l,int r)
    	{
    		if(l==r)
    		{
    			tree[rt].val=0;
    			tree[rt].sum=Base;
    			return;
    		}
    		tree[rt].val=1;
    		int mid=(l+r)>>1;
    		build(lson(rt),l,mid);
    		build(rson(rt),mid+1,r);
    	}
    	void pushdown(int rt)
    	{
    		if(tree[rt].lazy!=0)
    		{
    			if(tree[rt].lazy>0)
    			{
    				tree[lson(rt)].sum=tree[lson(rt)].sum*Fib[tree[rt].lazy];
    				tree[rson(rt)].sum=tree[rson(rt)].sum*Fib[tree[rt].lazy];
    			}
    			else
    			{
    				tree[lson(rt)].sum=tree[lson(rt)].sum*invFib[-tree[rt].lazy];
    				tree[rson(rt)].sum=tree[rson(rt)].sum*invFib[-tree[rt].lazy];
    			}
    			tree[lson(rt)].lazy+=tree[rt].lazy;
    			tree[rson(rt)].lazy+=tree[rt].lazy;
    			tree[rt].lazy=0;
    		}
    	}
    	void update1(int rt,int l,int r,int pos,int val)
    	{
    		if(l==r)
    		{
    			tree[rt].val=val;
    			return;
    		}
    		pushdown(rt);
    		int mid=(l+r)>>1;
    		if(pos<=mid)
    		{
    			update1(lson(rt),l,mid,pos,val);
    			tree[rson(rt)].sum=tree[rson(rt)].sum*Base;
    			tree[rson(rt)].lazy++;
    		}
    		else
    		{
    			update1(rson(rt),mid+1,r,pos,val);
    		}
    		pushup(rt);
    	}
    	void update2(int rt,int l,int r,int pos,int val)
    	{
    		if(l==r)
    		{
    			tree[rt].val=val;
    			return;
    		}
    		pushdown(rt);
    		int mid=(l+r)>>1;
    		if(pos<=mid)
    		{
    			update2(lson(rt),l,mid,pos,val);
    			tree[rson(rt)].sum=tree[rson(rt)].sum*invBase;
    			tree[rson(rt)].lazy--;
    		}
    		else
    		{
    			update2(rson(rt),mid+1,r,pos,val);
    		}
    		pushup(rt);
    	}
    }T;
    void init(int n,int m)
    {
    	klen=n/sqrt(m)+1;
    	ksum=n/klen;
    	for(int i=1;i<=ksum;i++)
    	{
    		L[i]=R[i-1]+1;
    		R[i]=R[i-1]+klen;
    	}
    	if(R[ksum]<n)
    	{
    		ksum++;
    		L[ksum]=R[ksum-1]+1;
    		R[ksum]=n;
    	}
    	for(int i=1;i<=ksum;i++)
    	{
    		for(int j=L[i];j<=R[i];j++)
    		{
    			pos[j]=i;
    		}
    	}
    	Base.ma[0]=1;     Base.ma[1]=1;     Base.ma[2]=1;     Base.ma[3]=0;
    	invBase.ma[0]=0;  invBase.ma[1]=1;  invBase.ma[2]=1;  invBase.ma[3]=p-1;
    	Fib[0].ma[0]=1;   Fib[0].ma[1]=0;   Fib[0].ma[2]=0;   Fib[0].ma[3]=1;
    	invFib[0].ma[0]=1;invFib[0].ma[1]=0;invFib[0].ma[2]=0;invFib[0].ma[3]=1;
    	for(int i=1;i<=n;i++)
    	{
    		Fib[i]=Fib[i-1]*Base;
    		invFib[i]=invFib[i-1]*invBase;
    	}
    	T.build(1,1,b[0]);
    }
    void add(int x)
    {
    	cnt[a[x]]++;
    	if(cnt[a[x]]==1)
    	{
    		T.update1(1,1,b[0],a[x],c[x]);
    	}
    }
    void del(int x)
    {
    	cnt[a[x]]--;
    	if(cnt[a[x]]==0)
    	{
    		T.update2(1,1,b[0],a[x],0);
    	}
    }
    int main()
    {
    	int n,m,l,r,i;
    	scanf("%d%d",&n,&p);
    	for(i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		b[i]=a[i];
    		c[i]=a[i]%p;
    	}
    	sort(b+1,b+1+n);
    	b[0]=unique(b+1,b+1+n)-(b+1);
    	for(i=1;i<=n;i++)
    	{
    		a[i]=lower_bound(b+1,b+1+b[0],a[i])-b;
    	}
    	scanf("%d",&m);
    	for(i=1;i<=m;i++)
    	{
    		scanf("%d%d",&q[i].l,&q[i].r);
    		q[i].id=i;
    	}
    	init(n,m);
    	sort(q+1,q+1+m,q_cmp);
    	for(i=1,l=1,r=0;i<=m;i++)
    	{
    		while(l>q[i].l)
    		{
    			l--;
    			add(l);
    		}
    		while(r<q[i].r)
    		{
    			r++;
    			add(r);
    		}
    		while(l<q[i].l)
    		{
    			del(l);
    			l++;
    		}
    		while(r>q[i].r)
    		{
    			del(r);
    			r--;
    		}
    		ans[q[i].id]=T.tree[1].sum.ma[1];
    	}
    	for(int i=1;i<=m;i++)
    	{
    		printf("%d\n",ans[i]);
    	}
    	return 0;
    }
    

2025--炼石计划-- 11 月 13 日 --NOIP 模拟赛 #20 T1 A. 邻间的骰子之舞

CF920F SUM and REPLACE

  • 并查集维护跳跃。

    点击查看代码
    ll a[300010],d[1000010];
    struct BIT
    {
    	ll c[300010];
    	ll lowbit(ll x)
    	{
    		return (x&(-x));
    	}
    	void add(ll n,ll x,ll val)
    	{
    		for(ll i=x;i<=n;i+=lowbit(i))
    		{
    			c[i]+=val;
    		}
    	}
    	ll getsum(ll x)
    	{
    		ll ans=0;
    		for(ll i=x;i>=1;i-=lowbit(i))
    		{
    			ans+=c[i];
    		}
    		return ans;
    	}
    }T;
    struct DSU
    {
    	ll fa[300010];
    	void init(ll n)
    	{
    		for(ll i=1;i<=n;i++)
    		{
    			fa[i]=i;
    		}
    	}
    	ll find(ll x)
    	{
    		return fa[x]==x?x:fa[x]=find(fa[x]);
    	}
    }D;
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	int n,m,pd,l,r,i,j;
    	cin>>n>>m;
    	for(i=1;i<=n;i++)
    	{
    		cin>>a[i];
    		T.add(n,i,a[i]);
    	}
    	D.init(n+1);
    	for(i=1;i<=1000000;i++)
    	{
    		for(j=1;i*j<=1000000;j++)
    		{
    			d[i*j]++;
    		}	
    	}
    	for(i=1;i<=m;i++)
    	{
    		cin>>pd>>l>>r;
    		if(pd==1)
    		{
    			for(j=l;j<=r;j=D.find(D.fa[j+1]))
    			{
    				T.add(n,j,-a[j]);
    				a[j]=d[a[j]];
    				T.add(n,j,a[j]);
    				if(a[j]<=2)
    				{
    					D.fa[j]=D.fa[j+1];
    				}
    			}
    		}
    		else
    		{
    			cout<<T.getsum(r)-T.getsum(l-1)<<endl;
    		}
    	}
    	return 0;
    }
    

2025--炼石计划-- 11 月 13 日 --NOIP 模拟赛 #20 T2 B. 星海浮沉录

luogu P11275 微观戏剧

  • \(\operatorname{lcm}(u,v) \in [\max(u,v),uv]\) ,强制取到下界(走到 \(1\) 即可)。

  • \(\min(u+v,\operatorname{lcm}(u,v))\) 即可。

    点击查看代码
    #define ll __int128_t
    inline ll read()
    {
    	ll x=0,f=1;
    	char c=getchar();
    	while(c>'9'||c<'0')
    	{
    		if(c=='-')
    		{
    			f=-1;
    		}
    		c=getchar();
    	}
    	while('0'<=c&&c<='9')
    	{
    		x=x*10+c-'0';
    		c=getchar();
    	}
    	return x*f;
    }
    void write(ll x)
    {
    	if(x<0)
    	{
    		putchar('-');
    		x=-x;
    	}
    	if(x>9)
    	{
    		write(x/10);
    	}
    	putchar((x%10)+'0');
    }
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	ll q,x,y,i;
    	q=read();
    	for(i=1;i<=q;i++)
    	{
    		x=read();
    		y=read();
    		if(x==y)
    		{
    			cout<<0<<endl;
    		}
    		else
    		{
    			write(min(x+y,x/__gcd(x,y)*y));
    			cout<<endl;
    		}
    	}
    	return 0;
    }
    

luogu P11276 第一首歌

  • \(ss\) 中的截点删去 \(s\) 的最长 \(\operatorname{border}\)

    点击查看代码
    int nxt[1000010];
    char s[1000010];
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	int n,i,j;
    	cin>>(s+1);
    	n=strlen(s+1);
    	for(i=2,nxt[1]=j=0;i<=n;i++)
    	{
    		while(j>=1&&s[i]!=s[j+1])
    		{
    			j=nxt[j];
    		}
    		j+=(s[i]==s[j+1]);
    		nxt[i]=j;
    	}
    	cout<<(s+1)<<(s+nxt[n]+1)<<endl;
    	return 0;
    }
    

2025--炼石计划-- 11 月 13 日 --NOIP 模拟赛 #20 T4 D. 第八交响曲

11.15

闲话

  • 上午 \(7:30 \sim 12:00\) 打学校 \(OJ\) 的模拟赛。打完模拟赛后 \(huge\)\(T1\)\(hack\) 数据叉掉了所有人这事强调了下让我们写代码时思路更加严谨;然后就开始跟我们论证“饮水机是怎么坏的”,他总结出饮水机没有得到更换后,引导我们通过已学的物理知识得到水桶没放平、气压问题导致水流不下去,让我们以后换水桶的时候注意放好。但最后还是没人来换饮水机。
  • 下午放 @Charlie_ljk 的每日一歌《浮光》,由 @Charlie_ljk@oceans_of_stars “激情”演唱, \(huge\) 还调侃我们咋都没学过五笔输入法(因为当时他设置的输入法是五笔)。然后讲题。
  • 晚上突然整个机房的网都没了,\(feifei\) 说先让我们干点没网也能做的事情,他去找学校管理网络的老师请求解决问题。

做题纪要

HZTG5777. 暴力操作(opt)

luogu P7424 [THUPC2017] 天天爱射击

  • 考虑计算每块木板最后是被哪颗子弹贯穿而碎掉的。

  • 以横坐标为下标插入主席树,然后维护静态区间第 \(k\) 大即可。

    点击查看代码
    int l[200010],r[200010],s[200010],ans[200010];
    vector<int>pos[200010];
    struct PDS_SMT
    {
    	int root[200010],rt_sum;
    	struct SegmentTree
    	{
    		int ls,rs,sum;
    	}tree[200010<<5];
    	#define lson(rt) (tree[rt].ls)
    	#define rson(rt) (tree[rt].rs)
    	int build_rt()
    	{
    		rt_sum++;
    		lson(rt_sum)=rson(rt_sum)=tree[rt_sum].sum=0;
    		return rt_sum;
    	}
    	void build(int &rt,int l,int r)
    	{
    		rt=build_rt();
    		if(l==r)
    		{
    			return;
    		}
    		int mid=(l+r)/2;
    		build(lson(rt),l,mid);
    		build(rson(rt),mid+1,r);
    	}
    	void update(int pre,int &rt,int l,int r,int pos,int val)
    	{
    		rt=build_rt();
    		tree[rt]=tree[pre];
    		tree[rt].sum+=val;
    		if(l==r)
    		{
    			return;
    		}
    		int mid=(l+r)/2;
    		if(pos<=mid)
    		{
    			update(lson(pre),lson(rt),l,mid,pos,val);
    		}
    		else
    		{
    			update(rson(pre),rson(rt),mid+1,r,pos,val);
    		}
    	}
    	int query(int rt1,int rt2,int l,int r,int k)
    	{
    		if(l==r)
    		{
    			return l;
    		}
    		int mid=(l+r)/2,num=tree[lson(rt2)].sum-tree[lson(rt1)].sum;
    		if(num>=k)
    		{
    			return query(lson(rt1),lson(rt2),l,mid,k);
    		}
    		else
    		{
    			return query(rson(rt1),rson(rt2),mid+1,r,k-num);
    		}
    	}
    }T;
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	int n,m,x,tmp,i,j;
    	cin>>n>>m;
    	for(i=1;i<=n;i++)
    	{
    		cin>>l[i]>>r[i]>>s[i];
    	}
    	for(i=1;i<=m;i++)
    	{
    		cin>>x;
    		pos[x].push_back(i);
    	}
    	T.build(T.root[0],1,m);
    	for(i=1;i<=200000;i++)
    	{
    		T.root[i]=T.root[i-1];
    		for(j=0;j<pos[i].size();j++)
    		{
    			T.update(T.root[i],T.root[i],1,m,pos[i][j],1);
    		}
    	}
    	for(i=1;i<=n;i++)
    	{
    		if(T.tree[T.root[r[i]]].sum-T.tree[T.root[l[i]-1]].sum>=s[i])
    		{
    			ans[T.query(T.root[l[i]-1],T.root[r[i]],1,m,s[i])]++;
    		}
    	}
    	for(i=1;i<=m;i++)
    	{
    		cout<<ans[i]<<endl;
    	}
    	return 0;
    }
    

luogu P4588 [TJOI2018] 数学计算

  • 线段树维护时间轴。

    点击查看代码
    ll p;
    struct SMT
    {
    	struct SegmentTree
    	{
    		ll mul;
    	}tree[400010];
    	ll lson(ll x)
    	{
    		return x*2;
    	}
    	ll rson(ll x)
    	{
    		return x*2+1;
    	}
    	void pushup(ll rt)
    	{
    		tree[rt].mul=tree[lson(rt)].mul*tree[rson(rt)].mul%p;
    	}
    	void build(ll rt,ll l,ll r)
    	{
    		tree[rt].mul=1;
    		if(l==r)
    		{
    			return;
    		}
    		ll mid=(l+r)/2;
    		build(lson(rt),l,mid);
    		build(rson(rt),mid+1,r);
    	}
    	void update(ll rt,ll l,ll r,ll pos,ll val)
    	{
    		if(l==r)
    		{
    			tree[rt].mul=val%p;
    			return;
    		}
    		ll mid=(l+r)/2;
    		if(pos<=mid)
    		{
    			update(lson(rt),l,mid,pos,val);
    		}
    		else
    		{
    			update(rson(rt),mid+1,r,pos,val);
    		}
    		pushup(rt);
    	}
    }T;
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	ll t,n,pd,x,i,j;
    	cin>>t;
    	for(j=1;j<=t;j++)
    	{
    		cin>>n>>p;
    		T.build(1,1,n);
    		for(i=1;i<=n;i++)
    		{
    			cin>>pd>>x;
    			if(pd==1)
    			{
    				T.update(1,1,n,i,x);
    				cout<<T.tree[1].mul<<endl;
    			}
    			else
    			{
    				T.update(1,1,n,x,1);
    				cout<<T.tree[1].mul<<endl;
    			}
    		}
    	}
    	return 0;
    }	
    

luogu P5787 二分图 /【模板】线段树分治

  • 线段树分治板子。

    • 线段树分治常用于维护操作的删除(需要支持撤销的数据结构辅助),或信息只在某一个时间段内出现。
    • 考虑开一棵线段树维护时间轴,插入一段信息和普通线段树区间修改同理。考虑从根节点开始分治,并维护当前信息并,每遍历到一个节点就合并上这个节点的信息,到达叶子节点时的信息并就是对应时间段内的答案;回溯时撤销(开个栈保存更改)。
  • luogu P1525 [NOIP2010 提高组] 关押罪犯 ,二分图存在当且仅当不存在奇环,可以使用扩展域并查集维护,因需要撤销同时使用按秩合并。

    • 二分图要求每条边的两个端点不属于一个同一个部分。
    • 具体地,对于节点 \(i\) ,将其拆成两个点 \(i,i+n\) ,分别表示 \(i\)\(i\) 的对立点,那么和 \(i\) 的对立点在一个连通块内的点不能和 \(i\) 在同一个部分。连边时分别与对方的对立点连边。
  • 注意本题中 时间段时刻 的区别。

    点击查看代码
    int n,ans[200010];
    pair<int,int>e[200010];
    struct quality
    {
    	int id,fa,siz;
    };
    struct DSU
    {
    	int fa[200010],siz[200010];
    	int find(int x)
    	{
    		return fa[x]==x?x:find(fa[x]);
    	}
    	void init(int n)
    	{
    		for(int i=1;i<=n;i++)
    		{
    			fa[i]=i;
    			siz[i]=1;
    		}
    	}
    	void merge(int x,int y,stack<quality>&s)
    	{
    		x=find(x);
    		y=find(y);
    		if(x!=y)//本题中合并之前已经判断过不等了
    		{
    			s.push((quality){x,fa[x],siz[x]});
    			s.push((quality){y,fa[y],siz[y]});
    			if(siz[x]<siz[y])
    			{
    				swap(x,y);
    			}
    			fa[y]=x;
    			siz[x]+=siz[y];
    		}
    	}
    	void split(stack<quality>&s)
    	{
    		while(s.empty()==0)
    		{
    			fa[s.top().id]=s.top().fa;
    			siz[s.top().id]=s.top().siz;
    			s.pop();
    		}
    	}
    }D;
    struct SMT
    {
    	struct SegmentTree
    	{
    		vector<int>info;
    	}tree[800010];
    	int lson(int x)
    	{
    		return x*2;
    	}
    	int rson(int x)
    	{
    		return x*2+1;
    	}
    	void update(int rt,int l,int r,int x,int y,int id)
    	{
    		if(x<=l&&r<=y)	
    		{
    			tree[rt].info.push_back(id);
    			return;
    		}
    		int mid=(l+r)/2;
    		if(x<=mid)
    		{
    			update(lson(rt),l,mid,x,y,id);
    		}
    		if(y>mid)
    		{
    			update(rson(rt),mid+1,r,x,y,id);
    		}
    	}
    	void solve(int rt,int l,int r)
    	{
    		stack<quality>s;
    		int mid=(l+r)/2,flag=1,x,y;
    		for(int i=0;i<tree[rt].info.size();i++)
    		{
    			x=D.find(e[tree[rt].info[i]].first);
    			y=D.find(e[tree[rt].info[i]].second);
    			if(x==y)
    			{
    				flag=0;
    				break;
    			}
    			else
    			{
    				D.merge(e[tree[rt].info[i]].first,e[tree[rt].info[i]].second+n,s);
    				D.merge(e[tree[rt].info[i]].second,e[tree[rt].info[i]].first+n,s);
    			}
    		}
    		if(flag==0)
    		{
    			for(int i=l;i<=r;i++)
    			{
    				ans[i]=0;
    			}
    		}
    		else
    		{
    			if(l==r)
    			{
    				ans[l]=1;
    			}
    			else
    			{
    				solve(lson(rt),l,mid);
    				solve(rson(rt),mid+1,r);	
    			}
    		}
    		D.split(s);
    	}
    }T;
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	int m,k,l,r,i;
    	cin>>n>>m>>k;
    	for(i=1;i<=m;i++)
    	{
    		cin>>e[i].first>>e[i].second>>l>>r;
    		if(l+1<=r)
    		{
    			T.update(1,1,k,l+1,r,i);
    		}
    	}
    	D.init(2*n);
    	T.solve(1,1,k);
    	for(i=1;i<=k;i++)
    	{
    		cout<<((ans[i]==1)?"Yes":"No")<<endl;
    	}
    	return 0;	
    }
    

luogu B4052 [语言月赛 202411] Giants

  • 分支结构。

    点击查看代码
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	ll type,a,b,c,d;
    	cin>>type>>a>>b>>c>>d;
    	if(type==0)
    	{
    		cout<<a+b<<endl;
    	}
    	else
    	{
    		cout<<max(a-c,0ll)+max(b-d,0ll)<<endl;
    	}
    	return 0;
    }
    

luogu B4053 [语言月赛 202411] Legends Never Die

  • 分支结构。

    点击查看代码
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	ll a,b,c,k;
    	cin>>a>>b>>c>>k;
    	if(a+b>=k)
    	{
    		cout<<"Yes"<<endl;
    	}
    	else
    	{
    		cout<<"No"<<endl;
    	}
    	if(a+c>=k)
    	{
    		cout<<"Yes"<<endl;
    	}
    	else
    	{
    		cout<<"No"<<endl;
    	}
    	if(b+c>=k)
    	{
    		cout<<"Yes"<<endl;
    	}
    	else
    	{
    		cout<<"No"<<endl;
    	}
    	return 0;
    }
    

luogu B4054 [语言月赛 202411] K/D/A

  • 分支结构。

    点击查看代码
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	ll n,k,d,a,tmp,maxx=0,id=0,i;
    	char pd;
    	cin>>n;
    	for(i=1;i<=n;i++)
    	{
    		cin>>k;
    		cin>>pd;
    		cin>>d;
    		cin>>pd;
    		cin>>a;
    		if(k-d>=10)
    		{
    			tmp=k*(k-d)+a;
    		}
    		else
    		{
    			if(k>=d)
    			{
    				tmp=(k-d+1)*3+a;
    			}
    			else
    			{
    				tmp=a*2;
    			}
    		}
    		if(tmp>maxx)
    		{
    			maxx=tmp;
    			id=i;
    		}
    	}
    	cout<<id<<endl;
    	return 0;
    }
    

luogu B4055 [语言月赛 202411] Phoenix

  • 循环结构。

    点击查看代码
    ll a[1010];
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	ll n,cnt=1,maxx,i;
    	cin>>n;
    	for(i=1;i<=n;i++)
    	{
    		cin>>a[i];
    	}
    	maxx=a[n];
    	for(i=n-1;i>=1;i--)
    	{
    		cnt+=(a[i]>maxx);
    		maxx=max(maxx,a[i]);
    	}
    	cout<<cnt<<endl;
    	return 0;
    }
    

luogu B4056 [语言月赛 202411] 卡牌

  • 模拟。

    点击查看代码
    ll a[6],cnt[6];
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	ll x,n,i,j;
    	cin>>x>>n;
    	for(i=1;i<=n;i++)
    	{
    		for(j=1;j<=5;j++)
    		{
    			cin>>a[j];
    		}
    		sort(a+1,a+1+5);
    		for(j=5;j>=1;j--)
    		{
    			if(a[j]<=x)
    			{
    				x-=a[j];
    				cnt[a[j]]++;
    				break;
    			}
    		}
    	}
    	for(i=1;i<=5;i++)
    	{
    		cout<<cnt[i]<<" ";
    	}
    	cout<<endl;
    	cout<<x<<endl;
    	return 0;
    }
    

luogu B4057 [语言月赛 202411] Rise

  • 循环结构。

    点击查看代码
    int a[1010];
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	int n,m,l,r,k,ans,i,j;
    	string pd;
    	cin>>n>>m;
    	for(j=1;j<=m;j++)
    	{
    		cin>>pd;
    		if(pd=="water")
    		{
    			cin>>l>>r;
    			for(i=l;i<=r;i++)
    			{
    				a[i]++;
    			}
    		}
    		else
    		{
    			cin>>l>>r>>k;
    			ans=0;
    			for(i=l;i<=r;i++)
    			{
    				if(a[i]>=k)
    				{
    					ans++;
    					a[i]=0;
    				}
    			}
    			cout<<ans<<endl;
    		}
    	}
    	return 0;
    }
    

luogu B4058 [语言月赛 202411] 三角含数

  • 暴力检验。

    点击查看代码
    int a[10];
    int work(int x,int y,int z)
    {
    	return (x+y>z&&x+z>y&&y+z>x);
    }
    int check(int x)
    {
    	int len=0,ans=0;
    	while(x)
    	{
    		len++;
    		a[len]=x%10;
    		if(a[len]==0)
    		{
    			return 0;
    		}
    		x/=10;
    	}
    	sort(a+1,a+1+6);
    	do
    	{
    		ans|=(work(a[1],a[2],a[3])==1&&work(a[4],a[5],a[6])==1);
    	}while(next_permutation(a+1,a+1+6));
    	return ans;
    }
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	int l,r,ans=0,i;
    	cin>>l>>r;
    	for(i=l;i<=r;i++)
    	{
    		ans+=check(i);
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    

luogu B4059 [语言月赛 202411] Enemy

  • 模拟。

    点击查看代码
    char c[1010][1010];
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	int n,m,flag,cnt1,cnt2,i,j;
    	cin>>n>>m;
    	for(i=1;i<=n;i++)
    	{
    		flag=cnt1=cnt2=0;
    		for(j=1;j<=m;j++)
    		{
    			cin>>c[i][j];
    			cnt1+=(c[i][j]=='A');
    			cnt2+=(c[i][j]=='B');
    			flag|=(c[i][j]=='H')*j;
    		}
    		if(flag!=0)
    		{
    			for(j=1;j<=cnt1;j++)
    			{
    				c[i][j]='A';
    			}
    			for(j=cnt1+1;j<=flag-1;j++)
    			{
    				c[i][j]='#';
    			}
    			c[i][flag]='H';
    			for(j=flag+1;j<=m-cnt2;j++)
    			{
    				c[i][j]='#';
    			}
    			for(j=m-cnt2+1;j<=m;j++)
    			{
    				c[i][j]='B';
    			}
    		}
    		else
    		{
    			if(cnt1>cnt2)
    			{
    				for(j=1;j<=m-cnt1;j++)
    				{
    					c[i][j]='#';
    				}
    				for(j=m-cnt1+1;j<=m;j++)
    				{
    					c[i][j]='A';
    				}
    			}
    			if(cnt1==cnt2)
    			{
    				for(j=1;j<=m;j++)
    				{
    					c[i][j]='#';
    				}
    			}
    			if(cnt1<cnt2)
    			{
    				for(j=1;j<=cnt2;j++)
    				{
    					c[i][j]='B';
    				}
    				for(j=cnt2+1;j<=m;j++)
    				{
    					c[i][j]='#';
    				}
    			}
    		}
    	}
    	for(i=1;i<=n;i++)
    	{
    		for(j=1;j<=m;j++)
    		{
    			if((c[i][j]=='A'||c[i][j]=='B')&&((c[i-1][j]==c[i][j]||c[i+1][j]==c[i][j])))
    			{
    				cout<<"#";
    			}
    			else
    			{
    				cout<<c[i][j];
    			}
    		}
    		cout<<endl;
    	}
    	return 0;
    }
    

11.16

闲话

  • 侯操时德育主任强调在校园内禁止使用手机,否则视为重大违纪,开家长会时让家长把手机带来了或请假回家也不行;听隔壁级部说还要自备餐具,学校不再提供筷子。
  • 早读时听 \(field\) 说我们不用开家长会,家长进校后只要门卫不拦着就可以直接走,高二那边得等会儿。然后和 \(field\) 交涉上午模拟赛的事情,临吃早饭前 \(field\) 说让我们吃完饭直接去隔壁机房,就不打上午的模拟赛了,让改改题;隔壁机房高二的都搬来我们机房正常打模拟赛。
  • \(9:00\) 以后 \(field\) 让我们回宿舍收拾行李,拿到手机后和家长说家长会不用开但发现家长已经去开了,被迫在宿舍等着。中途因为某些原因信奥家长集体跑路了,遂在班主任的期中总结家长会前就出校了。
  • 然后就开始颓了。

做题纪要

CF938G Shortest Path Queries

  • luogu P4151 [WC2011] 最大XOR和路径 ,将环的长度扔到线性基里。

  • 线段树分治维护删除,对每个深度开一个线性基维护。

    点击查看代码
    int u[400010],v[400010],w[400010],st[400010],ed[400010],ans[200010];
    pair<int,int>e[200010];
    map<pair<int,int>,int>f;
    struct quality
    {
    	int id,fa,dis,siz;
    };
    struct DSU
    {
    	int fa[200010],dis[200010],siz[200010];
    	void init(int n)
    	{
    		for(int i=1;i<=n;i++)
    		{
    			fa[i]=i;
    			dis[i]=0;
    			siz[i]=1;
    		}
    	}
    	int find(int x)
    	{
    		return fa[x]==x?x:find(fa[x]);
    	}
    	int get_dis(int x)
    	{
    		return fa[x]==x?dis[x]:dis[x]^get_dis(fa[x]);
    	}
    	void merge(int x,int y,int z,stack<quality>&s)
    	{
    		x=find(x);
    		y=find(y);
    		if(x!=y)
    		{
    			s.push((quality){x,fa[x],dis[x],siz[x]});
    			s.push((quality){y,fa[y],dis[y],siz[y]});
    			if(siz[x]<siz[y])
    			{
    				swap(x,y);
    			}
    			fa[y]=x;
    			dis[y]=z;
    			siz[x]+=siz[y];
    		}
    	}
    	void split(stack<quality>&s)
    	{
    		while(s.empty()==0)
    		{
    			fa[s.top().id]=s.top().fa;
    			dis[s.top().id]=s.top().dis;
    			siz[s.top().id]=s.top().siz;
    			s.pop();
    		}
    	}
    }D;
    struct Liner_Base
    {
    	int d[32];
    	void insert(int x)
    	{
    		for(int i=30;i>=0;i--)
    		{
    			if((x>>i)&1)
    			{
    				if(d[i]==0)
    				{
    					d[i]=x;
    					break;
    				}
    				x^=d[i];
    			}
    		}
    	}
    	int query(int ans)
    	{
    		for(int i=30;i>=0;i--)
    		{
    			ans=min(ans,ans^d[i]);
    		}
    		return ans;
    	}
    }L[25];
    struct SMT
    {
    	struct SegmentTree
    	{
    		vector<int>info;
    	}tree[800010];
    	int lson(int x)
    	{
    		return x*2;
    	}
    	int rson(int x)
    	{
    		return x*2+1;
    	}
    	void update(int rt,int l,int r,int x,int y,int id)
    	{
    		if(x<=l&&r<=y)
    		{	
    			tree[rt].info.push_back(id);
    			return;
    		}
    		int mid=(l+r)/2;
    		if(x<=mid)
    		{
    			update(lson(rt),l,mid,x,y,id);
    		}
    		if(y>mid)
    		{
    			update(rson(rt),mid+1,r,x,y,id);
    		}
    	}
    	void solve(int rt,int l,int r,int dep)
    	{
    		stack<quality>s;
    		L[dep]=L[dep-1];
    		int mid=(l+r)/2,x,y,z;
    		for(int i=0;i<tree[rt].info.size();i++)
    		{
    			x=D.find(u[tree[rt].info[i]]);
    			y=D.find(v[tree[rt].info[i]]);
    			z=w[tree[rt].info[i]]^D.get_dis(u[tree[rt].info[i]])^D.get_dis(v[tree[rt].info[i]]);
    			if(x==y)
    			{
    				L[dep].insert(z);
    			}
    			else
    			{
    				D.merge(u[tree[rt].info[i]],v[tree[rt].info[i]],z,s);
    			}
    		}
    		if(l==r)
    		{
    			ans[l]=L[dep].query(D.get_dis(e[l].first)^D.get_dis(e[l].second));
    		}
    		else
    		{
    			solve(lson(rt),l,mid,dep+1);
    			solve(rson(rt),mid+1,r,dep+1);
    		}
    		D.split(s);
    	}
    }T;
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	int n,m,q,pd,tim=0,x,y,i;
    	cin>>n>>m;
    	for(i=1;i<=m;i++)
    	{
    		cin>>u[i]>>v[i]>>w[i];
    		f[make_pair(u[i],v[i])]=i;
    		st[i]=1;
    		ed[i]=-1;
    	}
    	cin>>q;
    	for(i=1;i<=q;i++)
    	{
    		cin>>pd;
    		if(pd==1)
    		{
    			m++;
    			cin>>u[m]>>v[m]>>w[m];
    			f[make_pair(u[m],v[m])]=m;
    			st[m]=tim+1;
    			ed[m]=-1;
    		}
    		if(pd==2)
    		{
    			cin>>x>>y;	
    			ed[f[make_pair(x,y)]]=tim;
    		}
    		if(pd==3)
    		{
    			tim++;
    			cin>>e[tim].first>>e[tim].second;
    		}
    	}
    	for(i=1;i<=m;i++)
    	{
    		ed[i]=(ed[i]==-1)?tim:ed[i];
    		if(st[i]<=ed[i])
    		{
    			T.update(1,1,tim,st[i],ed[i],i);
    		}
    	}
    	D.init(n);
    	T.solve(1,1,tim,1);
    	for(i=1;i<=tim;i++)
    	{
    		cout<<ans[i]<<endl;
    	}
    	return 0;
    }
    

BZOJ4184 shallot

  • 线段树分治维护线性基的删除。

    点击查看代码
    int a[500010],st[500010],ed[500010],ans[500010];
    map<int,int>f;
    struct Liner_Base
    {
    	int d[32];
    	void insert(int x)
    	{
    		for(int i=31;i>=0;i--)
    		{
    			if((x>>i)&1)
    			{
    				if(d[i]==0)
    				{
    					d[i]=x;
    					break;
    				}
    				x^=d[i];
    			}
    		}
    	}
    	int query()
    	{
    		int ans=0;
    		for(int i=31;i>=0;i--)
    		{
    			ans=max(ans,ans^d[i]);
    		}
    		return ans;
    	}
    }L[25];
    struct SMT
    {
    	struct SegmentTree
    	{
    		vector<int>info;
    	}tree[2000010];
    	int lson(int x)
    	{
    		return x*2;
    	}
    	int rson(int x)
    	{
    		return x*2+1;
    	}
    	void update(int rt,int l,int r,int x,int y,int id)
    	{
    		if(x<=l&&r<=y)
    		{
    			tree[rt].info.push_back(id);
    			return;
    		}
    		int mid=(l+r)/2;
    		if(x<=mid)
    		{
    			update(lson(rt),l,mid,x,y,id);
    		}
    		if(y>mid)
    		{
    			update(rson(rt),mid+1,r,x,y,id);
    		}
    	}
    	void solve(int rt,int l,int r,int dep)
    	{
    		L[dep]=L[dep-1];
    		int mid=(l+r)/2;
    		for(int i=0;i<tree[rt].info.size();i++)
    		{
    			L[dep].insert(a[tree[rt].info[i]]);
    		}
    		if(l==r)
    		{
    			ans[l]=L[dep].query();
    		}
    		else
    		{
    			solve(lson(rt),l,mid,dep+1);
    			solve(rson(rt),mid+1,r,dep+1);
    		}
    	}
    }T;
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	int n,i;
    	cin>>n;
    	for(i=1;i<=n;i++)
    	{
    		cin>>a[i];
    		if(a[i]>0)
    		{
    			st[i]=i;
    			f[a[i]]=i;
    			ed[i]=-1;
    		}
    		else
    		{
    			ed[f[-a[i]]]=i-1;
    		}
    	}
    	for(i=1;i<=n;i++)
    	{
    		if(a[i]>0)
    		{
    			ed[i]=(ed[i]==-1)?n:ed[i];
    			if(st[i]<=ed[i])
    			{
    				T.update(1,1,n,st[i],ed[i],i);
    			}
    		}
    	}
    	T.solve(1,1,n,1);
    	for(i=1;i<=n;i++)
    	{
    		cout<<ans[i]<<endl;
    	}
    	return 0;
    }
    

11.17

闲话

  • 进校后发现机房里没有教练,且我们机房因为高二走的时候模拟赛刚结束所以没开网。直到中午吃饭前机房里也没来教练,遂把手机留在机房了。
  • 下午起床坐电梯时看见零基础的来上课,到机房后看见 \(field\) 在隔壁机房遂打算把手机交给他,拿起手机后发现 \(field\) 去给零基础的上课了,然后又度过了一段没有网的生活。等 \(field\) 上完课回来把手机交了,并让其把网开了。然后 \(huge\) 进来了说 \(15:30\) 高二各班班主任要到宿舍里查手机、泡面、闲书等违禁品,如果有带泡面的自己保管好,也可以暂时带到机房里,算是体现信奥的“高贵”了。
  • 看了眼高二带来的违禁品,以泡面、闲书、薯片(因为无法确定是不是违禁品遂带来了)居多, \(huge\) 说等晚上下课后再拿回宿舍放好,并赶紧解决掉这些东西,下次查的时候可就没有提前通知了。 \(huge\) 转悠的时候让我们打起精神来,昨晚上熬通宵的自己想办法(没有明抓睡觉),改改题。
  • \(15:00\) 以后 \(huge\) 见来到机房的高二的人有点少,然后就颇为和善地问他们周六他们让几点到位,处罚措施是什么,然后就扯到了 \(huge\) 觉得这是“法不责众”,这次因为门卫拦着不让进且他让早到机房遂先算了,以后等我们回归 \(whk\) 后再也不能像这样在没有和班主任提前沟通好自己不能遵守某些规定的前提下违背规定。期间再次询问众人宿舍内是否还有违禁品,然后就谈起了他当时在 \(HZ\) 上学的时候只能带牛奶和应季水果,连面包都不让带(现在也只是这么规定,但没有真正落实下去),现在查我们违禁品的都是过来人,上次听级部说一个把手机放到充电宝里的人被查住了,并解释了下为什么充电宝、耳机也算违禁品——不可能只带了充电宝、耳机而不带手机,且手机里一般都是有游戏的,他手机里还有个消消乐呢;又开始讲学生和老师之间可能存在矛盾,直接原因就是之间的沟通存在着问题,所以家长也会跟着着急,我们以后也要注意和老师沟通的方式;他当时也有点厌学,原因是因为没有一个合理的宣泄的方式,加上他当时英语口语不好,就找各科老师用英语谈谈心。现在我们可能觉得他的某些管理不太合理( \(huge\) 说还有人在博客里写这个讨论时间的规定就是屎),但等我们回归 \(whk\) 后只会更加不适应,我们只能选择适应、找到一个合理的宣泄方式。真是搞不懂 \(huge\) 这几天都在想什么,感觉大部分都在为我们的后事考虑,但我现在就感觉有点厌学怎么办。
  • 接着放昨天模拟赛多校的讲题。

做题纪要

luogu P4585 [FJOI2015] 火星商店问题

  • 线段树套 \(01Trie\) 。时空复杂度为 \(O(n \log{n} \log{V})\) ,在 BZOJ4137 火星商店问题 上无法通过。

    点击查看代码
    int a[100010];
    struct Trie
    {
    	int son[30000010][2],last[30000010],rt_sum;
    	int build_rt()
    	{
    		rt_sum++;
    		return rt_sum;
    	}
    	void insert(int &rt,int s,int t)
    	{
    		rt=(rt==0)?build_rt():rt;
    		int x=rt;
    		for(int i=18;i>=0;i--)
    		{
    			if(son[x][(s>>i)&1]==0)
    			{
    				son[x][(s>>i)&1]=build_rt();
    			}
    			x=son[x][(s>>i)&1];
    			last[x]=max(last[x],t);
    		}
    	}
    	int query(int rt,int s,int t)
    	{
    		int ans=0;
    		for(int i=18;i>=0;i--)
    		{
    			if(son[rt][((s>>i)&1)^1]!=0&&last[son[rt][((s>>i)&1)^1]]>=t)
    			{
    				ans|=(1<<i);
    				rt=son[rt][((s>>i)&1)^1];
    			}
    			else
    			{
    				if(last[son[rt][(s>>i)&1]]>=t)
    				{
    					rt=son[rt][(s>>i)&1];
    				}
    				else
    				{
    					break;
    				}
    			}
    		}
    		return ans;
    	}
    }T;
    struct SMT
    {
    	struct SegmentTree
    	{
    		int rt;
    	}tree[400010];
    	int lson(int x)
    	{
    		return x*2;
    	} 
    	int rson(int x)
    	{
    		return x*2+1;
    	}
    	void bulid(int rt,int l,int r)
    	{
    		for(int i=l;i<=r;i++)
    		{
    			T.insert(tree[rt].rt,a[i],0x3f3f3f3f);
    		}
    		if(l==r)
    		{
    			return;
    		}
    		int mid=(l+r)/2;
    		bulid(lson(rt),l,mid);
    		bulid(rson(rt),mid+1,r);
    	}
    	void update(int rt,int l,int r,int pos,int val,int t)
    	{
    		T.insert(tree[rt].rt,val,t);
    		if(l==r)
    		{
    			return;
    		}
    		int mid=(l+r)/2;
    		if(pos<=mid)
    		{
    			update(lson(rt),l,mid,pos,val,t);
    		}
    		else
    		{
    			update(rson(rt),mid+1,r,pos,val,t);
    		}
    	}
    	int query(int rt,int l,int r,int x,int y,int val,int t)
    	{
    		if(x<=l&&r<=y)
    		{
    			return T.query(tree[rt].rt,val,t);
    		}
    		int mid=(l+r)/2,ans=0;
    		if(x<=mid)
    		{
    			ans=max(ans,query(lson(rt),l,mid,x,y,val,t));
    		}
    		if(y>mid)
    		{
    			ans=max(ans,query(rson(rt),mid+1,r,x,y,val,t));
    		}
    		return ans;
    	}
    }S;
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	int n,m,pd,s,v,l,r,x,d,tim=0,i;
    	cin>>n>>m;
    	for(i=1;i<=n;i++)
    	{
    		cin>>a[i];
    	}
    	S.bulid(1,1,n);
    	for(i=1;i<=m;i++)
    	{
    		cin>>pd;
    		if(pd==0)
    		{
    			cin>>s>>v;
    			tim++;
    			S.update(1,1,n,s,v,tim);
    		}
    		else
    		{
    			cin>>l>>r>>x>>d;
    			cout<<S.query(1,1,n,l,r,x,tim-d+1)<<endl;
    		}
    	}
    	return 0;
    }
    

HZTG5778. 异或连通(xor)

HZTG5780. 民主投票(election)

[ABC077D] Small Multiple

[ABC216G] 01Sequence

11.18

闲话

  • 侯操时德育主任说以后违纪生跑操时要进行整改表态。
  • 早上到机房后 \(miaomiao\) 没让我们上早读。
  • 上午 \(7:30 \sim 12:00\)\(WFLS\) 的一起打学校 \(OJ\) 的模拟赛。模拟赛临开始时 \(miaomiao\) 说机房 \(8:30\) 之前只能出不能进,估计是说出去后就得在楼道里站着。
  • 下午放 \(huge\) 的每日一歌《青花瓷》,由 @hh弟中弟@CTHoi “激情演唱”。
  • 详见 2024 CSP-S 游记 11.18
  • 晚上讲题; \(miaomiao\) 说模拟赛别觉得自己模拟赛题看了题解以为自己会了就不改题了,模拟赛出这么多原题都没切得想想自己的原因;我看百度热搜时又被 \(miaomiao\) 抓了,看的内容没上次的内容正经,但 \(miaomiao\) 没说啥。

做题纪要

luogu P5556 圣剑护符

  • 由线性基的构造,存在两个互不相等的子集异或和相等当且仅当存在未成功插入线性基的数。

  • \(u,v\) 两点间距离 \(>31\) 时一定有解,否则暴力跳即可。

    点击查看代码
    struct node
    {
    	int nxt,to;
    }e[200010];
    int head[200010],siz[200010],fa[200010],dep[200010],son[200010],dfn[200010],out[200010],pos[200010],top[200010],c[200010],cnt=0,tot=0;
    void add(int u,int v)
    {
    	cnt++;
    	e[cnt].nxt=head[u];
    	e[cnt].to=v;
    	head[u]=cnt;
    }
    void dfs1(int x,int father)
    {
    	siz[x]=1;
    	fa[x]=father;
    	dep[x]=dep[father]+1;
    	for(int i=head[x];i!=0;i=e[i].nxt)
    	{
    		if(e[i].to!=father)
    		{
    			dfs1(e[i].to,x);
    			siz[x]+=siz[e[i].to];
    			son[x]=(siz[e[i].to]>siz[son[x]])?e[i].to:son[x];
    		}
    	}
    }
    void dfs2(int x,int id)
    {
    	top[x]=id;
    	tot++;
    	dfn[x]=tot;
    	pos[tot]=x;
    	if(son[x]!=0)
    	{
    		dfs2(son[x],id);
    		for(int i=head[x];i!=0;i=e[i].nxt)
    		{
    			if(e[i].to!=fa[x]&&e[i].to!=son[x])
    			{
    				dfs2(e[i].to,e[i].to);
    			}
    		}
    	}
    	out[x]=tot;
    }
    int lca(int u,int v)
    {
    	while(top[u]!=top[v])
    	{
    		if(dep[top[u]]>dep[top[v]])
    		{
    			u=fa[top[u]];
    		}
    		else
    		{
    			v=fa[top[v]];
    		}
    	}
    	return dep[u]<dep[v]?u:v;
    }
    struct SMT
    {
    	struct SegmentTree
    	{
    		int lazy,sum;
    	}tree[400010];
    	int lson(int x)
    	{
    		return x*2;
    	}
    	int rson(int x)
    	{
    		return x*2+1;
    	}
    	void pushdown(int rt)
    	{
    		if(tree[rt].lazy!=0)
    		{
    			tree[lson(rt)].lazy^=tree[rt].lazy;
    			tree[rson(rt)].lazy^=tree[rt].lazy;
    			tree[lson(rt)].sum^=tree[rt].lazy;
    			tree[rson(rt)].sum^=tree[rt].lazy;
    			tree[rt].lazy=0;
    		}
    	}
    	void build(int rt,int l,int r)
    	{
    		if(l==r)
    		{
    			tree[rt].sum=c[pos[l]];
    			return;
    		}
    		int mid=(l+r)/2;
    		build(lson(rt),l,mid);
    		build(rson(rt),mid+1,r);
    	}
    	void update(int rt,int l,int r,int x,int y,int val)
    	{
    		if(x<=l&&r<=y)
    		{
    			tree[rt].lazy^=val;
    			tree[rt].sum^=val;
    			return;
    		}
    		pushdown(rt);
    		int mid=(l+r)/2;
    		if(x<=mid)
    		{
    			update(lson(rt),l,mid,x,y,val);
    		}
    		if(y>mid)
    		{
    			update(rson(rt),mid+1,r,x,y,val);
    		}
    	}
    	int query(int rt,int l,int r,int pos)
    	{
    		if(l==r)
    		{
    			return tree[rt].sum;
    		}
    		pushdown(rt);
    		int mid=(l+r)/2;
    		if(pos<=mid)
    		{
    			return query(lson(rt),l,mid,pos);
    		}
    		else
    		{
    			return query(rson(rt),mid+1,r,pos);
    		}
    	}
    }T;
    struct Liner_Base
    {
    	int d[32];
    	void init()
    	{
    		memset(d,0,sizeof(d));
    	}
    	bool insert(int x)
    	{
    		for(int i=30;i>=0;i--)	
    		{
    			if((x>>i)&1)
    			{
    				if(d[i]==0)
    				{
    					d[i]=x;
    					return true;
    				}
    				x^=d[i];
    			}
    		}
    		return false;
    	}
    }L;
    void update1(int u,int v,int w,int n)
    {
    	while(top[u]!=top[v])
    	{
    		if(dep[top[u]]>dep[top[v]])
    		{
    			T.update(1,1,n,dfn[top[u]],dfn[u],w);
    			u=fa[top[u]];
    		}
    		else
    		{
    			T.update(1,1,n,dfn[top[v]],dfn[v],w);
    			v=fa[top[v]];
    		}
    	}
    	if(dep[u]<dep[v])
    	{
    		T.update(1,1,n,dfn[u],dfn[v],w);
    	}
    	else
    	{
    		T.update(1,1,n,dfn[v],dfn[u],w);
    	}
    }
    int query1(int u,int v,int n)
    {
    	int rt=lca(u,v),ans;
    	if(dep[u]+dep[v]-2*dep[rt]>31)
    	{
    		return 1;
    	}
    	L.init();
    	ans=L.insert(T.query(1,1,n,dfn[rt]));
    	while(u!=rt)
    	{
    		ans&=L.insert(T.query(1,1,n,dfn[u]));
    		u=fa[u];
    	}
    	while (v!=rt)
    	{
    		ans&=L.insert(T.query(1,1,n,dfn[v]));
    		v=fa[v];
    	}
    	return ans^1;
    }
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	int n,m,u,v,w,i;
    	string pd;
    	cin>>n>>m;
    	for(i=1;i<=n;i++)
    	{
    		cin>>c[i];
    	}
    	for(i=1;i<=n-1;i++)
    	{
    		cin>>u>>v;
    		add(u,v);
    		add(v,u);
    	}
    	dfs1(1,0);
    	dfs2(1,1);
    	T.build(1,1,n);
    	for(i=1;i<=m;i++)
    	{
    		cin>>pd>>u>>v;
    		if(pd=="Update")
    		{
    			cin>>w;
    			update1(u,v,w,n);
    		}
    		else
    		{	
    			cout<<((query1(u,v,n)==1)?"YES":"NO")<<endl;
    		}
    	}
    	return 0;
    }
    

luogu P5948 [POI2003] Chocolate

luogu P1080 [NOIP2012 提高组] 国王游戏

  • 考虑临项交换。

  • 若交换 \(i,i+1\) 后更优则等价于 \(\max(\left\lfloor \dfrac{\prod_{j=0}^{i-1}a_{j}}{b_{i}} \right\rfloor,\left\lfloor \dfrac{\prod_{j=0}^{i}a_{j}}{b_{i+1}} \right\rfloor) \ge \max(\left\lfloor \dfrac{\prod_{j=0}^{i-1}a_{j}}{b_{i+1}} \right\rfloor,\left\lfloor \dfrac{a_{i+1} \times \prod_{j=0}^{i-1}a_{j}}{b_{i}} \right\rfloor)\) ,即 \(\max( \frac{1}{b_{i}}, \frac{a_{i}}{b_{i+1}}) \ge \max( \frac{1}{b_{i+1}}, \frac{a_{i+1}}{b_{i}})\)

  • 又因为 \(\frac{a_{i}}{b_{i+1}} \ge \frac{1}{b_{i+1}}, \frac{a_{i}+1}{b_{i}} \ge \frac{1}{b_{i}}\) ,等价于 \(\frac{a_{i}}{b_{i+1}} \ge \frac{a_{i+1}}{b_{i}}\) ,移项得到 \(a_{i}b_{i} \ge a_{i+1}b_{i+1}\)

  • 高精度部分来自 @xrlong板子

    点击查看代码
    namespace BIG_num{
    	using cpx=complex<double>;const double PI=acos(-1);vector<cpx>roots= {{0,0},{1,0}};
    	void ensure_capacity(int min_capacity) {
    		for(int len=roots.size(); len<min_capacity; len*=2) {for(int i=len>>1; i<len; i++) {
    			roots.emplace_back(roots[i]);double angle=2*PI*(2*i+1-len)/(len*2);roots.emplace_back(cos(angle),sin(angle));
    		}}
    	}
    	void fft(vector<cpx>&z,bool inverse) {
    		int n=z.size();ensure_capacity(n);
    		for(int i=1,j=0; i<n; i++) {int BIGt=n>>1;for(; j>=BIGt; BIGt>>=1)j-=BIGt;j+=BIGt;if(i<j)swap(z[i],z[j]);}
    		for(int len=1; len<n; len<<=1) {for(int i=0; i<n; i+=len*2) {for(int j=0; j<len; j++) {
    			cpx root=inverse?conj(roots[j+len]):roots[j+len];cpx u=z[i+j];cpx v=z[i+j+len]*root;z[i+j]=u+v;z[i+j+len]=u-v;
    		}}}if(inverse)for(int i=0; i<n; i++)z[i]/=n;
    	}
    	vector<int>multiply_BIG(const vector<int>&a,const vector<int>&b,int base) {
    		int need=a.size()+b.size();int n=1;while(n<need)n<<=1;vector<cpx>p(n);
    		for(int i=0; i<n; i++) {p[i]=cpx(i<(int)a.size()?a[i]:0,i<(int)b.size()?b[i]:0);}
    		fft(p,false);vector<cpx>ab(n);cpx r(0,-0.25);
    		for(int i=0; i<n; i++) {int j=(n-i)&(n-1);ab[i]=(p[i]*p[i]-conj(p[j]*p[j]))*r;}
    		fft(ab,true);vector<int>result(need);long long carry=0;
    		for(int i=0; i<need; i++) {long long d=(long long)(ab[i].real()+0.5)+carry;carry=d/base;result[i]=d%base;}
    		return result;
    	}
    	vector<int>multiply_mod(const vector<int>&a,const vector<int>&b,int m) {
    		int need=a.size()+b.size()-1;int n=1;while(n<need)n<<=1;vector<cpx>A(n);
    		for(size_t i=0; i<a.size(); i++) {int x=(a[i]%m+m)%m;A[i]=cpx(x&((1<<15)-1),x>>15);}
    		fft(A,false);vector<cpx>B(n);
    		for(size_t i=0; i<b.size(); i++) {int x=(b[i]%m+m)%m;B[i]=cpx(x&((1<<15)-1),x>>15);}
    		fft(B,false);vector<cpx>fa(n);vector<cpx>fb(n);
    		for(int i=0,j=0; i<n; i++,j=n-i) {
    			cpx a1=(A[i]+conj(A[j]))*cpx(0.5,0);cpx a2=(A[i]-conj(A[j]))*cpx(0,-0.5);
    			cpx b1=(B[i]+conj(B[j]))*cpx(0.5,0);cpx b2=(B[i]-conj(B[j]))*cpx(0,-0.5);
    			fa[i]=a1*b1+a2*b2*cpx(0,1);fb[i]=a1*b2+a2*b1;
    		}fft(fa,true);fft(fb,true);vector<int>res(need);
    		for(int i=0; i<need; i++) {
    			long long aa=(long long)(fa[i].real()+0.5);long long bb=(long long)(fb[i].real()+0.5);
    			long long cc=(long long)(fa[i].imag()+0.5);res[i]=(aa%m+(bb%m<<15)+(cc%m<<30))%m;
    		}return res;
    	}
    	constexpr int digits(int base)noexcept {return base<=1?0:1+digits(base/10);} constexpr int base=1000000000;
    	constexpr int base_digits=digits(base);constexpr int fft_base=10000;constexpr int fft_base_digits=digits(fft_base);
    	struct BIG {
    		vector<int>z;int sign;
    		BIG(long long v=0) {*this=v;} 
    		BIG&operator=(long long v) {
    			sign=v<0?-1:1;v*=sign;z.clear();for(; v>0; v=v/base)z.push_back((int)(v%base));return*this;} 
    		BIG(const string&s) {read(s);} 
    		BIG&operator+=(const BIG&other) {
    			if(sign==other.sign) {for(int i=0,carry=0; i<(int)other.z.size()||carry; ++i) {
    					if(i==(int)z.size())z.push_back(0);z[i]+=carry+(i<(int)other.z.size()?other.z[i]:0);
    					carry=z[i]>=base;if(carry)z[i]-=base;
    			}} else if(other!=0) {*this-=-other;}return*this;} 
    		friend BIG operator+(BIG a,const BIG&b) {a+=b;return a;} 
    		BIG&operator-=(const BIG&other) {if(sign==other.sign) 
    			{if((sign==1&&*this>=other)||(sign==-1&&*this<=other)){for(int i=0,carry=0;i<(int)other.z.size()||carry;++i)
    			{z[i]-=carry+(i<(int)other.z.size()?other.z[i]:0);carry=z[i]<0;if(carry)z[i]+=base;}trim();
    			} else {*this=other-*this;this->sign=-this->sign;}} else {*this+=-other;}return*this;} 
    		friend BIG operator-(BIG a,const BIG&b) {a-=b;return a;}
    		BIG&operator*=(int v) {if(v<0)sign=-sign,v=-v;
    			for(int i=0,carry=0; i<(int)z.size()||carry; ++i) {
    				if(i==(int)z.size())z.push_back(0);long long cur=(long long)z[i]*v+carry;
    				carry=(int)(cur/base);z[i]=(int)(cur%base);
    			}trim();return*this;} 
    		BIG operator*(int v)const {return BIG(*this)*=v;}
    		friend pair<BIG,BIG>divmod(const BIG&a1,const BIG&b1) {
    			int norm=base/(b1.z.back()+1);BIG a=a1.abs()*norm;BIG b=b1.abs()*norm;BIG q,r;q.z.resize(a.z.size());
    			for(int i=(int)a.z.size()-1; i>=0; i--) {
    				r*=base;r+=a.z[i];int s1=b.z.size()<r.z.size()?r.z[b.z.size()]:0;
    				int s2=b.z.size()-1<r.z.size()?r.z[b.z.size()-1]:0;int d=(int)(((long long)s1*base+s2)/b.z.back());
    				r-=b*d;while(r<0)r+=b,--d;q.z[i]=d;
    			}q.sign=a1.sign*b1.sign;r.sign=a1.sign;q.trim();r.trim();return {q,r/norm};} 
    		friend BIG sqrt(const BIG&a1) {BIG a=a1;
    			while(a.z.empty()||a.z.size()%2==1)a.z.push_back(0);int n=a.z.size();
    			int firstDigit=(int)::sqrt((double)a.z[n-1]*base+a.z[n-2]);int norm=base/(firstDigit+1);
    			a*=norm;a*=norm;while(a.z.empty()||a.z.size()%2==1)a.z.push_back(0);BIG r=(long long)a.z[n-1]*base+a.z[n-2];
    			firstDigit=(int)::sqrt((double)a.z[n-1]*base+a.z[n-2]);int q=firstDigit;BIG res;
    			for(int j=n/2-1; j>=0; j--) {for(;; --q) {
    				BIG r1=(r-(res*2*base+q)*q)*base*base+(j>0?(long long)a.z[2*j-1]*base+a.z[2*j-2]:0);if(r1>=0){r=r1;break;}
    				}res*=base;res+=q;if(j>0) {
    					int d1=res.z.size()+2<r.z.size()?r.z[res.z.size()+2]:0;
    					int d2=res.z.size()+1<r.z.size()?r.z[res.z.size()+1]:0;
    					int d3=res.z.size()<r.z.size()?r.z[res.z.size()]:0;
    					q=(int)(((long long)d1*base*base+(long long)d2*base+d3)/(firstDigit*2));
    			}}res.trim();return res/norm;} 
    		BIG operator/(const BIG&v)const {return divmod(*this,v).first;} 
    		BIG operator%(const BIG&v)const {return divmod(*this,v).second;} 
    		BIG&operator/=(int v) {if(v<0)sign=-sign,v=-v;
    			for(int i=(int)z.size()-1,rem=0; i>=0; --i) {
    				long long cur=z[i]+rem*(long long)base;z[i]=(int)(cur/v);rem=(int)(cur%v);
    			}trim();return*this;} 
    		BIG operator/(int v)const {return BIG(*this)/=v;} 
    		int operator%(int v)const {
    			if(v<0)v=-v;int m=0;for(int i=(int)z.size()-1; i>=0; --i)m=(int)((z[i]+m*(long long)base)%v);return m*sign;} 
    		BIG&operator*=(const BIG&v) {*this=*this*v;return*this;} 
    		BIG&operator/=(const BIG&v) {*this=*this/v;return*this;} 
    		BIG&operator%=(const BIG&v) {*this=*this%v;return*this;} 
    		bool operator<(const BIG&v)const {if(sign!=v.sign)return sign<v.sign;
    			if(z.size()!=v.z.size())return z.size()*sign<v.z.size()*v.sign;
    			for(int i=(int)z.size()-1; i>=0; i--)if(z[i]!=v.z[i])return z[i]*sign<v.z[i]*sign;return false;} 
    		bool operator>(const BIG&v)const {return v<*this;} 
    		bool operator<=(const BIG&v)const {return!(v<*this);} 
    		bool operator>=(const BIG&v)const {return!(*this<v);} 
    		bool operator==(const BIG&v)const {return sign==v.sign&&z==v.z;} 
    		bool operator!=(const BIG&v)const {return!(*this==v);
    		}void trim(){while(!z.empty()&&z.back()==0)z.pop_back();if(z.empty())sign=1;} 
    		bool isZero()const {return z.empty();} 
    		friend BIG operator-(BIG v) {if(!v.z.empty())v.sign=-v.sign;return v;} 
    		BIG abs()const {return sign==1?*this:-*this;} 
    		long long to_num()const {
    			long long res=0;for(int i=(int)z.size()-1; i>=0; i--)res=res*base+z[i];return res*sign;} 
    		friend BIG __gcd(const BIG&a,const BIG&b) {return b.isZero()?a:__gcd(b,a%b);} 
    		friend BIG abs(const BIG&a) {return a.abs();}
    		void read(const string&s) {
    			sign=1;z.clear();int pos=0;
    			while(pos<(int)s.size()&&(s[pos]=='-'||s[pos]=='+')) {if(s[pos]=='-')sign=-sign;++pos;}
    			for(int i=(int)s.size()-1; i>=pos; i-=base_digits) {int x=0;
    				for(int j=max(pos,i-base_digits+1); j<=i; j++)x=x*10+s[j]-'0';z.push_back(x);
    			}trim();} 
    		friend istream&operator>>(istream&stream,BIG&v) {string s;stream>>s;v.read(s);return stream;} 
    		friend ostream&operator<<(ostream&stream,const BIG&v) {
    			if(v.sign==-1)stream<<'-';stream<<(v.z.empty()?0:v.z.back());
    			for(int i=(int)v.z.size()-2; i>=0; --i)stream<<setw(base_digits)<<setfill('0')<<v.z[i];return stream;
    		} static vector<int>convert_base(const vector<int>&a,int old_digits,int new_digits) {
    			vector<long long>p(max(old_digits,new_digits)+1);p[0]=1;
    			for(int i=1; i<(int)p.size(); i++)p[i]=p[i-1]*10;vector<int>res;long long cur=0;int cur_digits=0;
    			for(int v:a) {cur+=v*p[cur_digits];cur_digits+=old_digits;while(cur_digits>=new_digits)
    				{res.push_back(int(cur%p[new_digits]));cur/=p[new_digits];cur_digits-=new_digits;}
    			}res.push_back((int)cur);while(!res.empty()&&res.back()==0)res.pop_back();return res;} 
    		BIG operator*(const BIG&v)const {
    			if(min(z.size(),v.z.size())<150)return mul_simple(v);BIG res;res.sign=sign*v.sign;
    			res.z=multiply_BIG(convert_base(z,base_digits,fft_base_digits),convert_base(v.z,base_digits,fft_base_digits),fft_base);
    			res.z=convert_base(res.z,fft_base_digits,base_digits);res.trim();return res;} 
    		BIG mul_simple(const BIG&v)const {BIG res;res.sign=sign*v.sign;res.z.resize(z.size()+v.z.size());
    			for(int i=0; i<(int)z.size(); ++i)if(z[i])for(int j=0,carry=0; j<(int)v.z.size()||carry; ++j) {
    				long long cur=res.z[i+j]+(long long)z[i]*(j<(int)v.z.size()?v.z[j]:0)+carry;
    				carry=(int)(cur/base);res.z[i+j]=(int)(cur%base);
    			}res.trim();return res;
    		}
    	};
    	mt19937 rng(std::chrono::system_clock::now().time_since_epoch().count());
    	BIG BIG_rnd(int n) {string s;for(int i=0; i<n; i++) {s+=uniform_int_distribution<int>('0','9')(rng);}return BIG(s);}
    } using BIG_num::BIG;
    BIG ans=0,mul;
    pair<int,int>a[1010];
    bool cmp(pair<int,int>a,pair<int,int>b)
    {
    	return a.first*a.second<b.first*b.second;
    }
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	int n,i;
    	cin>>n;
    	for(i=0;i<=n;i++)
    	{
    		cin>>a[i].first>>a[i].second;
    	}
    	sort(a+1,a+1+n,cmp);
    	mul=a[0].first;
    	for(i=1;i<=n;i++)
    	{
    		ans=max(ans,mul/a[i].second);
    		mul*=a[i].first;
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    

luogu P5221 Product

  • 推式子,有 \(\begin{aligned} &\prod\limits_{i=1}^{n}\prod\limits_{j=1}^{n}\frac{\operatorname{lcm}(i,j)}{\gcd(i,j)} \\ &=\prod\limits_{i=1}^{n}\prod\limits_{j=1}^{n}\frac{ij}{\gcd(i,j)^{2}} \\ &=(\prod\limits_{i=1}^{n}\prod\limits_{j=1}^{n}ij)(\prod\limits_{i=1}^{n}\prod\limits_{j=1}^{n}\gcd(i,j))^{-2} \\ &=(n!)^{2n}(\prod\limits_{d=1}^{n}d^{\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}[\gcd(i,j)=d]})^{-2} \\ &=(n!)^{2n}(\prod\limits_{d=1}^{n}d^{-1+2\sum\limits_{i=1}^{\left\lfloor \frac{n}{d} \right\rfloor}\varphi(i)})^{-2} \end{aligned}\)

  • 由扩展欧拉定理使 \(-1+2\sum\limits_{i=1}^{\left\lfloor \frac{n}{d} \right\rfloor}\varphi(i)\)int 范围内。

    点击查看代码
    const int p=104857601,phip=104857600;
    int prime[1000010],vis[1000010],phi[1000010],sum[1000010],len=0;
    void isprime(int n)
    {
    	memset(vis,0,sizeof(vis));
    	phi[1]=1;
    	for(int i=2;i<=n;i++)
    	{
    		if(vis[i]==0)
    		{
    			len++;
    			prime[len]=i;
    			phi[i]=i-1;
    		}
    		for(int j=1;j<=len&&i*prime[j]<=n;j++)
    		{
    			vis[i*prime[j]]=1;
    			if(i%prime[j]==0)
    			{
    				phi[i*prime[j]]=phi[i]*prime[j];
    				break;
    			}
    			else
    			{
    				phi[i*prime[j]]=phi[i]*(prime[j]-1);
    			}
    		}
    	}
    	for(int i=1;i<=n;i++)
    	{
    		sum[i]=(sum[i-1]+phi[i])%phip;
    	}
    }
    int qpow(int a,int b,int p)
    {
    	int ans=1;
    	while(b)
    	{
    		if(b&1)
    		{
    			ans=1ll*ans*a%p;
    		}
    		b>>=1;
    		a=1ll*a*a%p;
    	}
    	return ans;
    }
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	int n,mul=1,jc=1,i;
    	cin>>n;
    	isprime(n);
    	for(i=1;i<=n;i++)
    	{
    		jc=1ll*jc*i%p;
    		mul=1ll*mul*qpow(i,(2*sum[n/i]%phip-1+phip)%phip,p)%p;
    	}
    	cout<<1ll*qpow(jc,2*n,p)*qpow(1ll*mul*mul%p,p-2,p)%p<<endl;
    	return 0;
    }
    

QOJ 8077. Madeline and Badeline

11.19

闲话

  • 侯操时落实了昨天的违纪生表态制度。
  • 早读到机房后发现电脑被全部重启了,被迫重新调配置, \(field\) 说等我们调完配置就早读。
  • 上午 \(7:30 \sim 12:00\) 打 accoders NOI 的模拟赛。中途电脑因为火狐死机了,被迫重新调配置。
  • 下午放 @oceans_of_stars 的每日一歌《罗生门》。听完多校的讲题后就跟着高二的去上体育课了, \(feifei\) 还说“高一的跟着高二的一起下去玩去吧”。
  • 详见 2024 CSP-S 游记 11.19
  • 晚上 \(field\) 来转悠的时候让我们看国足世预赛18强赛中国 VS 日本不要太激动,他窥屏的时候看见好几个都放着此百度热搜直播。

做题纪要

QOJ 1286. Ternary String Counting

P505. 选取字符串

P507. 均衡区间

P506. 取石子

luogu P4602 [CTSC2018] 混合果汁

  • 先按照 \(\{ d \}\) 降序排序。

  • 考虑二分答案。 \(check\) 时以 \(\{ p \}\) 为下标计算总量和,然后主席树上二分维护即可。

    点击查看代码
    struct node
    {
    	ll d,p,l;
    }a[100010];
    bool cmp(node a,node b)
    {
    	return a.d>b.d;
    }
    struct PDS_SMT
    {
    	ll root[100010],rt_sum=0;
    	struct SegmentTree
    	{
    		ll ls,rs,v,sum;
    	}tree[100010<<5];
    	#define lson(rt) (tree[rt].ls)
    	#define rson(rt) (tree[rt].rs)
    	ll build_rt()
    	{
    		rt_sum++;
    		lson(rt_sum)=rson(rt_sum)=tree[rt_sum].v=tree[rt_sum].sum=0;
    		return rt_sum;
    	}
    	void update(ll pre,ll &rt,ll l,ll r,ll pos,ll v,ll val)
    	{
    		rt=build_rt();
    		tree[rt]=tree[pre];
    		tree[rt].v+=v;
    		tree[rt].sum+=val;
    		if(l==r)
    		{
    			return;
    		}
    		ll mid=(l+r)/2;
    		if(pos<=mid)
    		{
    			update(lson(pre),lson(rt),l,mid,pos,v,val);
    		}
    		else 
    		{
    			update(rson(pre),rson(rt),mid+1,r,pos,v,val);
    		}
    	}
    	ll query(ll rt,ll l,ll r,ll k)
    	{
    		if(l==r)
    		{
    			return l*k;
    		}
    		ll mid=(l+r)/2;
    		if(tree[lson(rt)].v>=k)
    		{
    			return query(lson(rt),l,mid,k);
    		}
    		else
    		{
    			return tree[lson(rt)].sum+query(rson(rt),mid+1,r,k-tree[lson(rt)].v);
    		}
    	}
    }T;
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	ll n,m,g,minv,l,r,mid,ans,i;
    	cin>>n>>m;
    	for(i=1;i<=n;i++)
    	{
    		cin>>a[i].d>>a[i].p>>a[i].l;
    	}
    	sort(a+1,a+1+n,cmp);
    	for(i=1;i<=n;i++)
    	{
    		T.update(T.root[i-1],T.root[i],1,100000,a[i].p,a[i].l,a[i].p*a[i].l);
    	}
    	for(i=1;i<=m;i++)
    	{
    		cin>>g>>minv;
    		l=1;
    		r=n;
    		ans=-1;
    		while(l<=r)
    		{
    			mid=(l+r)/2;
    			if(T.tree[T.root[mid]].v>=minv&&T.query(T.root[mid],1,100000,minv)<=g)
    			{
    				ans=mid;
    				r=mid-1;
    			}
    			else
    			{
    				l=mid+1;
    			}
    		}
    		cout<<(ans==-1?-1:a[ans].d)<<endl;
    	}
    	return 0;
    }
    

11.20

闲话

  • 今天的模拟赛不知道去哪里了, \(feifei\) 让我们把这几天的题好好改一下。
  • 上午 \(huge\) 又强调了下午晚休纪律,说就剩这几天了再一次停半天课不值得。
  • 下午 \(huge\) 强调了下上厕所问题,明确规定了时间点(早读,\(7:30 \sim 8:10\)\(11:30 \sim 12:15\)\(17:50 \sim 18:15\)\(21:10 \sim 21:40\))内不准去厕所。
  • 详见 2024 CSP-S 游记 11.20

做题纪要

P276. 排列

UVA11536 最短子序列 Smallest Sub-Array

  • 多倍经验: luogu P1638 逛画展 | CF1354B Ternary String

    点击查看代码
    int a[1000010],cnt[1010];
    deque<int>q;
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	int t,n,m,k,num,ans,i,j;
    	cin>>t;
    	for(j=1;j<=t;j++)
    	{
    		cin>>n>>m>>k;
    		q.clear();
    		num=0;
    		ans=0x7f7f7f7f;
    		a[1]=1;
    		a[2]=2;
    		a[3]=3;
    		memset(cnt,0,sizeof(cnt));
    		for(i=4;i<=n;i++)
    		{
    			a[i]=(a[i-1]+a[i-2]+a[i-3])%m+1;
    		}
    		for(i=1;i<=n;i++)
    		{
    			if(a[i]<=k)
    			{
    				num+=(cnt[a[i]]==0);
    				cnt[a[i]]++;
    				q.push_back(i);
    				while(q.empty()==0&&cnt[a[q.front()]]>=2)
    				{
    					cnt[a[q.front()]]--;
    					q.pop_front();
    				}
    				if(num==k)
    				{
    					ans=min(ans,i-q.front()+1);
    				}
    			}
    		}
    		cout<<"Case "<<j<<": ";
    		if(ans==0x7f7f7f7f)
    		{
    			cout<<"sequence nai"<<endl;
    		}
    		else
    		{
    			cout<<ans<<endl;
    		}
    	}
    	return 0;
    }
    

luogu P5160 WD与循环

  • 等价于求 \(\sum\limits_{i=1}^{n}x_{i} \le m\) 的非负整数解数量 \(\sum\limits_{i=0}^{m}\dbinom{n+i-1}{n-1}\)

  • 多校A层冲刺NOIP2024模拟赛18 T3 C. 人口局 DBA(dba) ,等价于求 \(\dbinom{n+m}{n}-\dbinom{n-1}{n}=\dbinom{n+m}{n}\) ,卢卡斯定理维护即可。

    点击查看代码
    const ll p=19491001;
    ll jc[20000010],inv[20000010],jc_inv[20000010];
    ll C(ll n,ll m,ll p)
    {
    	return (n>=m&&n>=0&&m>=0)?(jc[n]*jc_inv[n-m]%p)*jc_inv[m]%p:0;
    }
    ll lucas(ll n,ll m,ll p)
    {
    	return (n>=m&&n>=0&&m>=0)?(m?C(n%p,m%p,p)*lucas(n/p,m/p,p)%p:1):0;
    }
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	ll t,n,m,i;
    	cin>>t;
    	inv[1]=jc[0]=jc_inv[0]=jc[1]=jc_inv[1]=1;
    	for(i=2;i<=p-1;i++)
    	{
    		inv[i]=(p-p/i)*inv[p%i]%p;
    		jc[i]=jc[i-1]*i%p;
    		jc_inv[i]=jc_inv[i-1]*inv[i]%p;
    	}
    	for(i=1;i<=t;i++)
    	{
    		cin>>n>>m;
    		cout<<lucas(n+m,n,p)<<endl;
    	}
    	return 0;
    }
    

luogu P5148 大循环

  • 等价于求 \(f(q)\sum\limits_{1 \le a_{k}<a_{k-1}< \dots <a_{1} \le n}1=f(q)\dbinom{n}{k}\)

  • 秦九韶算法求 \(f(q)\) 即可。

    点击查看代码
    const ll p=1000000007;
    ll a[500010];
    ll qpow(ll a,ll b,ll p)
    {
    	ll ans=1;
    	while(b)
    	{
    		if(b&1)
    		{
    			ans=ans*a%p;
    		}
    		b>>=1;
    		a=a*a%p;
    	}
    	return ans;
    }
    ll C(ll n,ll m,ll p)
    {
    	if(n>=m&&n>=0&&m>=0)
    	{
    		ll up=1,down=1;
    		for(ll i=n-m+1;i<=n;i++)
    		{
    			up=up*i%p;
    		}
    		for(ll i=1;i<=m;i++)
    		{
    			down=down*i%p;
    		}
    		return up*qpow(down,p-2,p)%p;
    	}
    	else
    	{
    		return 0;
    	}
    }
    ll f(ll n,ll x,ll p)
    {
    	x%=p;
    	ll ans=a[n];
    	for(ll i=n;i>=1;i--)
    	{
    		ans=(ans*x%p+a[i-1])%p;
    	}
    	return ans;
    }
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	ll n,m,k,q,i;
    	cin>>n>>m>>k>>q;
    	for(i=0;i<=m;i++)
    	{
    		cin>>a[i];
    	}
    	cout<<C(n,k,p)*f(m,q,p)%p<<endl;
    	return 0;
    }
    

luogu P5151 HKE与他的小朋友

  • 多倍经验: UVA306 Cipher

  • 快速幂加速置换复合。

    点击查看代码
    int ans[100010];
    struct Permutation
    {
    	int pos[100010];
    	void init(int n)
    	{
    		for(int i=1;i<=n;i++)
    		{
    			pos[i]=i;	
    		}
    	}
    }per;
    Permutation mul(Permutation a,Permutation b,int n)
    {
    	Permutation tmp=a;
    	for(int i=1;i<=n;i++)
    	{
    		tmp.pos[i]=b.pos[a.pos[i]];
    	}
    	return tmp;
    }
    Permutation qpow(Permutation a,int b,int n)
    {
    	Permutation ans;
    	ans.init(n);
    	while(b)
    	{
    		if(b&1)
    		{
    			ans=mul(ans,a,n);
    		}
    		b>>=1;
    		a=mul(a,a,n);
    	}
    	return ans;
    }
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	int n,k,i;
    	cin>>n>>k;
    	for(i=1;i<=n;i++)
    	{
    		cin>>per.pos[i];
    	}
    	per=qpow(per,k,n);
    	for(i=1;i<=n;i++)
    	{
    		ans[per.pos[i]]=i;
    	}
    	for(i=1;i<=n;i++)
    	{
    		cout<<ans[i]<<" ";
    	}
    	return 0;
    }
    

HDU1873 看病要排队

  • 优先队列。

    点击查看代码
    priority_queue<pair<int,int> >q[4];
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	int n,tim,a,b,i;
    	string pd;
    	while(cin>>n)
    	{
    		tim=0;
    		for(i=1;i<=3;i++)
    		{
    			while(q[i].empty()==0)
    			{
    				q[i].pop();
    			}
    		}
    		for(i=1;i<=n;i++)
    		{
    			cin>>pd>>a;
    			if(pd=="IN")
    			{
    				cin>>b;
    				tim++;
    				q[a].push(make_pair(b,-tim));
    			}
    			else
    			{
    				if(q[a].empty()==0)
    				{
    					cout<<-q[a].top().second<<endl;
    					q[a].pop();
    				}
    				else
    				{
    					cout<<"EMPTY"<<endl;
    				}
    			}
    		}
    	}
    	return 0;
    }
    

P508. 禁止套娃

luogu P4067 [SDOI2016] 储能表

  • 等价于查询 \(\sum\limits_{i=0}^{n-1}\sum\limits_{j=0}^{m-1}[i \bigoplus j \ge k](i \bigoplus j-k)\) ,考虑统计满足 \(i \bigoplus j \ge k\) 的点对数量 \(s_{1}\) 和其总和 \(s_{2}\) ,此时 \(s_{2}-s_{1}k\) 即为所求。

  • \(f_{pos,0/1,0/1,0/1}\) 表示处理至第 \(pos\) 位时, \(i\) 没有取到/取到上界, \(j\) 没有取到/取到上界,选出的 \(i \bigoplus j\) 没有取到/取到下界的点对数量及总和。

  • 从高到低转移,中途若 \(i \bigoplus j>k\) 则后面一直 \(>k\) 可以一直无脑统计贡献。

    点击查看代码
    ll mi[64],n,m,k,p;
    pair<ll,ll>f[64][2][2][2];
    bool vis[64][2][2][2];
    pair<ll,ll> dfs(ll pos,ll limiti,ll limitj,ll limitk)
    {
    	if(pos==-1)
    	{
    		return make_pair(1,0);
    	}
    	if(vis[pos][limiti][limitj][limitk]==1)
    	{
    		return f[pos][limiti][limitj][limitk];
    	}
    	vis[pos][limiti][limitj][limitk]=1;
    	ll maxi=(limiti==0)?1:((n>>pos)&1),maxj=(limitj==0)?1:((m>>pos)&1),mink=(k>>pos)&1;
    	pair<ll,ll>ans=make_pair(0,0),tmp;
    	for(ll i=0;i<=maxi;i++)
    	{
    		for(ll j=0;j<=maxj;j++)
    		{
    			if(limitk==0||(i^j)>=mink)
    			{
    				tmp=dfs(pos-1,(i==maxi)*limiti,(j==maxj)*limitj,((i^j)==mink)*limitk);
    				ans.first=(ans.first+tmp.first)%p;
    				ans.second=(ans.second+tmp.second+tmp.first*(i^j)*mi[pos]%p)%p;
    			}
    		}
    	}
    	return f[pos][limiti][limitj][limitk]=ans;
    }
    ll ask()
    {
    	pair<ll,ll>tmp=dfs(60,1,1,1);
    	k%=p;
    	return (tmp.second-tmp.first*k%p+p)%p;
    }
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	ll t,i,j;
    	cin>>t;
    	for(j=1;j<=t;j++)
    	{
    		cin>>n>>m>>k>>p;
    		n--;
    		m--;
    		mi[0]=1;
    		for(i=1;i<=60;i++)
    		{
    			mi[i]=mi[i-1]*2%p;
    		}
    		memset(vis,0,sizeof(vis));
    		cout<<ask()<<endl;
    	}
    	return 0;
    }
    
posted @ 2024-11-10 21:13  hzoi_Shadow  阅读(58)  评论(0编辑  收藏  举报
扩大
缩小