2019-9-15 雜題選講

2019-9-15 雜題選講

題目

CF1174E Ehab and the Expected GCD Problem

link

這題給人的大概感覺就是,前綴GCDGCD是不增的,那麼我們既然想要前綴GCDGCD儘量不同,我們必然希望它慢慢地下降,每次降一丟丟,那麼我每次就只允許它降一半就是最優的咯,於是這就有了NTFNTF的結論的感性理解版。但是第一個數並不一定是22的次冪,有可能帶一個33,因爲乘最後一個22時,如果加個33不會爆nn,加個33也是可以的。於是第一個數就是2x3y(y=1or0)2^x3^y(y=1 or 0),於是上DPDP計數即可

[ZJOI2019]線段樹

恭喜此題榮獲本週的鎮題之寶
link

震驚!天天打線段樹的人竟不知線段樹中有這五種點
這題的大致思路如下。首先每棵樹的編號(相對順序)是不影響答案的,我們只需要知道每次複製了一遍,新的modifymodify,舊的不動。那麼我們設計狀態fu,if_{u,i}表示i次操作後有多少個uu點有tagtag,我們將點分類之後分別寫出DPDP方程,發現還需維護一個gu,ig_{u,i}表示ii次操作後有多少個uu點到11的路徑上沒有tagtag,來輔助計算ff,這些線段樹上的點經過分類後可以發現,有的是每次個數不超過O(logn)O(logn)級別,有的則是一棵小子樹,那麼前者暴力修改,後者用正常的lazytaglazy tag即可

CF1197D Yet Another Subarray Problem

link

這題就是推式子的時候令i=imm+i%mi=\lfloor \frac{i}{m}\rfloor *m+i \%m即可,由於m很小從左往右掃的時候維護前綴最小值時按%m分類即可

P4965 薇爾莉特的打字機

link

這題代碼easyeasy但是思路sogoodso good。我們先考慮在trietrie樹上分析這個問題

  • 若一個把可以到達的點上做一個標記,那麼加入一個字符時所有的標記點都拓展出一個新點,並且舊點仍然保留標記,那麼我們就維護好F[c]F[c]表示擁有邊cc的節點個數即可快速轉移
  • 若收到一個退格,多出來的答案就只有一個,就是原串從開始到這個退格之前的串,於是ans++ans++,但是退格了之後相當於某個點向上走了一步,那麼這個位置的點雖然已經有了一個標記,但是我們要把它當作兩個點,於是F[x]++F[x]++,然後這題就沒了

P2405 non天平

link

這題的思維難度不高,必然首先把物品轉成nn進制,由於我們兩邊都能放砝碼,相當於我們可以用一個大砝碼減去一些小法碼,從而得到原本用一些小砝碼稱出來的東西,但是這個相減的操作必定出現在大小相鄰的兩個砝碼之間,而且必定大砝碼只會用一個,除非我是傻的,那麼從高到低DPDP即可

代碼

CF1174E Ehab and the Expected GCD Problem代碼

#include<bits/stdc++.h>
#define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
#define For(i,a,b) for (register int i=(a);i>=(b);i--)
#define mem(i,j) memset(i,j,sizeof(i))
#define GO(u) for (register int j=f[u];j!=-1;j=nxt[j])
using namespace std;
typedef long long ll;
const int N=1e6+5;
const int mod=1e9+7;
int n,dp[N][21][2],lim=1,lg=0,ans;
int er[N],san[N];
inline int read()
{
	int x=0,f=1;
	char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return f*x;
}
inline void write(int x)
{
	if (x<0) putchar('-'),x=-x;
	if (x>9) write(x/10);
	putchar(x%10+'0');
	return;
}
inline int CAL(int x,int y)
{
	if (x<0||y<0) return 0;
	if (!er[x]||!san[y]) return 0;
	int ret=n/(er[x]*san[y]);
	return ret;
}
int main()
{
	mem(dp,0);
	n=read();
	while ((lim<<1)<=n) lim<<=1,lg++;
	er[0]=1;
	FOR(i,1,lg) er[i]=1LL*er[i-1]*2%mod;
	san[0]=1;
	for (register int i=1;san[i-1]*3<=n;i++) san[i]=1LL*san[i-1]*3%mod;
	dp[1][lg][0]=1;
	if (er[lg-1]*3<=n) dp[1][lg-1][1]=1;
	FOR(i,2,n)
		FOR(x,0,lg)
		{
			dp[i][x][0]=(1LL*dp[i-1][x][0]*(CAL(x,0)-i+1)%mod+1LL*dp[i-1][x][1]*(CAL(x,0)-CAL(x,1))%mod+1LL*dp[i-1][x+1][0]*(CAL(x,0)-CAL(x+1,0))%mod)%mod;
			dp[i][x][1]=(1LL*dp[i-1][x][1]*(CAL(x,1)-i+1)%mod+1LL*dp[i-1][x+1][1]*(CAL(x,1)-CAL(x+1,1))%mod)%mod;
		}
	ans=dp[n][0][0];
	write(ans);
	return 0;
}

[ZJOI2019]線段樹代碼

#include<bits/stdc++.h>
#define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
#define For(i,a,b) for (register int i=(a);i>=(b);i--)
#define mem(i,j) memset(i,j,sizeof(i))
#define GO(u) for (register int j=f[u];j!=-1;j=nxt[j])
using namespace std;
typedef long long ll;
const int N=2e5+5;
const int mod=998244353;
int n,m,cnt=1,opt,tmp1,tmp2,ans[N];
int sum[N<<2],f[N<<2],g[N<<2],tag_f[N<<2],tag_g[N<<2];
inline int read()
{
	int x=0,f=1;
	char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return f*x;
}
inline void write(int x)
{
	if (x<0) putchar('-'),x=-x;
	if (x>9) write(x/10);
	putchar(x%10+'0');
	return;
}
inline void up(int p)
{
	sum[p]=(1LL*sum[p<<1]+sum[p<<1|1]+f[p])%mod;
	return;
}
inline void bd(int p,int l,int r)
{
	sum[p]=f[p]=0;
	g[p]=1;
	tag_f[p]=tag_g[p]=1;
	if (l==r) return;
	int mid=(l+r)>>1,ls=p<<1,rs=p<<1|1;
	bd(ls,l,mid);
	bd(rs,mid+1,r);
	up(p);
	return;
}
inline void mul_f(int p,int v)
{
	tag_f[p]=1LL*tag_f[p]*v%mod;
	sum[p]=1LL*sum[p]*v%mod;
	f[p]=1LL*f[p]*v%mod;
	return;
}
inline void mul_g(int p,int v)
{
	tag_g[p]=1LL*tag_g[p]*v%mod;
	g[p]=1LL*g[p]*v%mod;
	return;
}
inline void down(int p)
{
	int ls=p<<1,rs=p<<1|1;
	if (tag_f[p]!=1)
	{
		mul_f(ls,tag_f[p]);
		mul_f(rs,tag_f[p]);
		tag_f[p]=1;
	}
	if (tag_g[p]!=1)
	{
		mul_g(ls,tag_g[p]);
		mul_g(rs,tag_g[p]);
		tag_g[p]=1;
	}
	return;
}
inline void md(int p,int l,int r,int L,int R)
{
	down(p);
	int mid=(l+r)>>1,ls=p<<1,rs=p<<1|1;
	if (L<=l&&r<=R)
	{
		mul_f(ls,2);mul_f(rs,2);
		f[p]=(1LL*f[p]+cnt)%mod;
		up(p);
		return;
	}
	g[p]=(1LL*g[p]+cnt)%mod;
	if (R<=mid)
	{
		md(ls,l,mid,L,R);
		down(rs);
		f[rs]=(1LL*f[rs]+cnt-g[rs]+mod)%mod;
		g[rs]=(1LL*g[rs]+g[rs])%mod;
		mul_g(rs<<1,2);mul_g(rs<<1|1,2);
		mul_f(rs<<1,2);mul_f(rs<<1|1,2);
		up(rs);
	}
	else if (L>mid)
	{
		md(rs,mid+1,r,L,R);
		down(ls);
		f[ls]=(1LL*f[ls]+cnt-g[ls]+mod)%mod;
		g[ls]=(1LL*g[ls]+g[ls])%mod;
		mul_g(ls<<1,2);mul_g(ls<<1|1,2);
		mul_f(ls<<1,2);mul_f(ls<<1|1,2);
		up(ls);
	}
	else
	{
		md(ls,l,mid,L,R);
		md(rs,mid+1,r,L,R);
	}
	up(p);
	return;
}
int main()
{
//	freopen("data.in","r",stdin);
	n=read(),m=read();
	bd(1,1,n);
	FOR(i,1,m)
	{
		opt=read();
		if (opt==1) tmp1=read(),tmp2=read();
		if (opt==1) md(1,1,n,tmp1,tmp2),cnt=(1LL*cnt+cnt)%mod;
		else ans[++ans[0]]=sum[1];
	}
	FOR(i,1,ans[0]) write(ans[i]),putchar('\n');
	return 0;
}

CF1197D Yet Another Subarray Problem代碼

#include<bits/stdc++.h>
#define FOR(i,a,b) for (register ll i=(a);i<=(b);i++)
#define For(i,a,b) for (register ll i=(a);i>=(b);i--)
#define mem(i,j) memset(i,j,sizeof(i))
#define GO(u) for (register ll j=f[u];j!=-1;j=nxt[j])
using namespace std;
typedef long long ll;
const ll N=3e5+5;
const ll inf=1e17;
ll n,m,k,a[N],s[N],mn[20],r[N],tmp,ans=0;
inline ll read()
{
	ll x=0,f=1;
	char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return f*x;
}
inline void write(ll x)
{
	if (x<0) putchar('-'),x=-x;
	if (x>9) write(x/10);
	putchar(x%10+'0');
	return;
}
int main()
{
	n=read(),m=read(),k=read();
	FOR(i,1,m-1) mn[i]=inf;
	FOR(i,1,n) a[i]=read();
	FOR(i,1,n) s[i]=s[i-1]+a[i];
	FOR(i,1,n) r[i]=s[i]-k*(i/m);
	FOR(i,1,n)
	{
		tmp=i%m;
		FOR(j,0,m-1) ans=max(ans,r[i]-mn[j]-k*((i%m-j+m-1)/m));
		mn[tmp]=min(mn[tmp],r[i]);
	}
	write(ans);
	return 0;
}

P4965 薇爾莉特的打字機代碼

#include<bits/stdc++.h>
#define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
#define For(i,a,b) for (register int i=(a);i>=(b);i--)
#define mem(i,j) memset(i,j,sizeof(i))
#define GO(u) for (register int j=f[u];j!=-1;j=nxt[j])
using namespace std;
typedef long long ll;
const int N=5e6+5;
const int mod=19260817;
int n,m,ans=1,rest,F[100];
char A[N],B[N];
inline int read()
{
	int x=0,f=1;
	char c=getchar();
	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
	while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return f*x;
}
inline void write(int x)
{
	if (x<0) putchar('-'),x=-x;
	if (x>9) write(x/10);
	putchar(x%10+'0');
	return;
}
int main()
{
	n=read(),m=read();
	rest=n;
	scanf("%s",A+1);
	scanf("%s",B+1);
	FOR(i,1,m)
	{
		int c=B[i]-'A'+1;
		if (1<=c&&c<=26)
		{
			int f=F[c];
			F[c]=ans;
			ans=(1LL*(ans<<1)-f+mod)%mod;
		}
		else
		{
			if (!rest) continue;
			ans++;
			ans%=mod;
			F[A[rest]-'A'+1]++;
			F[A[rest]-'A'+1]%=mod;
			rest--;
		}
	}
	write(ans);
	return 0;
}

P2405 non天平代碼

#include<bits/stdc++.h>
#define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
#define For(i,a,b) for (register int i=(a);i>=(b);i--)
#define mem(i,j) memset(i,j,sizeof(i))
#define GO(u) for (register int j=f[u];j!=-1;j=nxt[j])
using namespace std;
typedef long long ll;
const int N=2e6+5;
int n,s[N],tmps[N],len=0,r[N],dp[N][2],ans;
inline void write(int x)
{
	if (x<0) putchar('-'),x=-x;
	if (x>9) write(x/10);
	putchar(x%10+'0');
	return;
}
inline int get_yu()
{
	int ret=0;
	FOR(i,1,len)
	{
		ret=(ret<<1)+(ret<<3)+s[i];
		ret%=n;
	}
	return ret;
}
inline void devide()
{
	int now=0,tmplen=0,ready=0;
	FOR(i,1,len) tmps[i]=0;
	FOR(i,1,len)
	{
		now=(now<<1)+(now<<3)+s[i];
		if (now>=n) ready=1;
		if (ready)
		{
			tmps[++tmplen]=now/n;
			now%=n;
		}
	}
	len=tmplen;
	FOR(i,1,len) s[i]=tmps[i];
	return;
}
int main()
{
//	freopen("testdata (1).in","r",stdin);
	char c=getchar();
	while (c<'0'||c>'9') c=getchar();
	while (c>='0'&&c<='9') s[++len]=c-'0',c=getchar();
	scanf("%d",&n);
	if (n==1) {FOR(i,1,len) write(s[i]);exit(0);}
	while (len)
	{
		r[++r[0]]=get_yu();
		devide();
	}
	dp[r[0]+1][1]=1;
	For(i,r[0],1)
	{
		dp[i][0]=min(dp[i+1][0]+r[i],dp[i+1][1]+n-r[i]);
		dp[i][1]=min(dp[i+1][0]+r[i]+1,dp[i+1][1]+n-r[i]-1);
	}
	ans=dp[1][0];
	write(ans);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章