ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

noip模拟60(待补)

2021-09-24 07:02:41  阅读:112  来源: 互联网

标签:ch noip 待补 res ll 60 freopen sizeof define


A. 整除

式子还没推出来,先鸽着..

B. 糖果

很显然的矩阵乘,但是学习了倍增 \(dp\).

令 \(g_{i,j}\) 表示在同一个 \(a_i\) 的大小下,选了前 \(2_i\) 种,占了 \(j\) 个位置的方案数.

转移方程:\(g_{i,j}=\sum\limits_{k=0}^{k<=j}g_{i-1,k}*g_{i-1,j-k}*C_j^k\)

后面的 \(C_j^k\) 可以理解为前面已经排好之后的可重排列数.

后面直接背包转移就可以了.

B_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
	#define ll long long int
	#define ull unsigned ll
	#define lf double
	#define lbt(x) (x&(-x))
	#define mp(x,y) make_pair(x,y)
	#define lb lower_bound 
	#define ub upper_bound
	#define Fill(x,y) memset(x,y,sizeof x)
	#define Copy(x,y) memcpy(x,y,sizeof x)
	#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
	inline ll read() {
		ll res=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0; 
		while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
		return cit?res:-res;
	}
} using namespace BSS;

const ll M=107,mod=998244353;

ll m,n,A,B,P,cnt,len,tot,lg2;
ll vis[(int)1e7+21],num[(int)1e7+21];
ll tms[M],val[M],c2[M];
ll g[65][M],f[M][65][M],C[M][M],dp[M][M];
signed main(){
	File(sugar);
	n=read(),m=read(),num[1]=read(),A=read(),B=read(),P=read(),vis[num[1]]=1,lg2=log2(n)+1;
	for(int i=0;i<=100;i++){
		C[i][0]=1;
		for(int j=1;j<=i;j++)
			C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
	}
	for(ll i=2;i<=n;i++){
		num[i]=(num[i-1]*A%P+B)%P+1;
		if(vis[num[i]]){ cnt=i-1,len=i-vis[num[i]]; break; }
		vis[num[i]]=i;
	}
	if(!cnt) len=n,cnt=n;
	for(int i=1;i<=cnt;i++) vis[num[i]]=0;
	for(int i=1;i<=cnt-len;i++){
		num[i]=min(num[i],m);
		if(!vis[num[i]]) val[++tot]=num[i],vis[num[i]]=1;
		tms[num[i]]++;
	}
	for(ll i=cnt-len+1;i<=cnt;i++){
		num[i]=min(num[i],m);
		if(!vis[num[i]]) val[++tot]=num[i],vis[num[i]]=1;
		tms[num[i]]+=(n-(cnt-len))/len+((n-(cnt-len))%len>=i-(cnt-len));
	}
	for(int i=1;i<=m;i++){
		f[i][0][0]=1;
		if(!tms[i]) { f[i][0][0]=1; continue; }
		Fill(g,0); 
		for(int j=0;j<=i;j++) g[0][j]=1;
		for(int j=1;j<=lg2;j++)
			for(int k=0;k<=m;k++)
				for(int h=0;h<=k;h++)
					g[j][k]=(g[j][k]+g[j-1][h]*g[j-1][k-h]%mod*C[k][h]%mod)%mod;
		for(int j=0;j<=lg2;j++){
			if(!((tms[i]>>j)&1)) continue;
			c2[i]++;
			for(int k=0;k<=m;k++)
				for(int h=0;h<=k;h++){
					f[i][c2[i]][k]=(f[i][c2[i]][k]+f[i][c2[i]-1][k-h]*g[j][h]%mod*C[k][h]%mod)%mod;
				}
		}	
	}
	dp[0][0]=1;
	for(int i=1;i<=m;i++){
		for(int j=0;j<=m;j++)
			for(int k=0;k<=j;k++){
				dp[i][j]=(dp[i][j]+dp[i-1][j-k]*f[i][c2[i]][k]%mod*C[j][k]%mod)%mod;
			}
	}
	printf("%lld\n",dp[m][m]%mod);
	exit(0);
}

C. 打字机

这东西感觉很神仙.

在转移前缀的同时更新作为答案的后缀.

单调的性质感觉也很难发现.

找性质一定朝题目所求的靠拢.

另外,一般的 \(dp\) 都是设 \(f_x=y\) ,一般都是已知 \(x\) 求合法 \(y\).

然而这次我们逆着,设已知 \(y\),寻找最优的 \(x\).

即 \(f_{i,j,k}\) 表示考虑了 \(S\) 长度为 \(i\) 的前缀,\(T\) 长度为 \(j\) 的前缀,最大的\(x\)使得 \(x-h(x)\le k\),\(h*(x)\) 和题解说的一样.

转移方程:\(f_{i,j,k} = min(f_{i−1,j,k}+1,f_{i,j−1,k+1},f_{i−1,j−1,k−[S_i==T_j]}+1)\)

但是转移时要用自己更新后面的,而不是用前面的更新自己,比较玄..

还有就是用 STL 偷懒不写负数会 T.

C_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
	#define ll int
	#define ull unsigned ll
	#define lf double
	#define lbt(x) (x&(-x))
	#define mp(x,y) make_pair(x,y)
	#define lb lower_bound 
	#define ub upper_bound
	#define Fill(x,y) memset(x,y,sizeof x)
	#define Copy(x,y) memcpy(x,y,sizeof x)
	#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
	inline ll read() {
		ll res=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0; 
		while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
		return cit?res:-res;
	}
} using namespace BSS;

const ll N=1e5+21,M=23,inf=1e9;

char s[N],t[M];

ll ls,lt,ops,ans,add;
ll f[N][M][M<<1];
signed main(){
	File(print);
	scanf("%s",s+1),scanf("%s",t+1),ls=strlen(s+1),lt=strlen(t+1),ops=read(),add=lt+1;
	Fill(f,0x3f);
	for(int i=0;i<=ls;i++){
		for(int j=0;j<=lt;j++) 
			for(int k=j;k<=lt;k++)
					f[i][j][-1-k+add]=-1;
	}
	for(int i=0;i<=lt;i++) f[0][0][-1-i+add]=-1,f[0][0][i+add]=0;
	for(int i=0;i<=ls;i++){
		for(int j=0;j<=lt;j++)
			for(int k=-lt-1;k<=lt;k++){
				if(i<ls) f[i+1][j][k+add]=min(f[i+1][j][k+add],f[i][j][k+add]+1);
				if(j<lt) f[i][j+1][k-1+add]=min(f[i][j+1][k-1+add],f[i][j][k+add]);
				if(i<ls and j<lt) f[i+1][j+1][k+(s[i+1]==t[j+1])+add]=min(f[i+1][j+1][k+(s[i+1]==t[j+1])+add],f[i][j][k+add]+1);
			}
	}
	ll l,r;		
	while(ops--){
		l=read(),r=read();
		for(int i=-lt-1;i<=lt;i++){
			if(f[r][lt][i+add]>=r-l+1) { ans=r-l+1-i; break; }
		}
		puts("");
		printf("%d\n",ans);
	}
	exit(0);
}

D. 堆

标签:ch,noip,待补,res,ll,60,freopen,sizeof,define
来源: https://www.cnblogs.com/AaMuXiiiiii/p/15328339.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有