[考试总结]noip模拟60

整除

这个题目只能膜拜战神。

正解的复杂度是要去积性筛的,然后战神直接推式子。

然后直接 \(20ms\) 解决战斗,人均 \(4000ms+\)

战神:我觉得数据范围还能加大

答案就是 \(\gcd(m-1,t[i]-1)+1\) 的乘积



#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register int i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
	#define file(a) FILE *FI = freopen(#a".in","r",stdin); FI = freopen(#a".out","w",stdout);
	#define debug cout<<"debug"<<endl
	#define sb(x) cout<<#x" = "<<x<<' '
	#define jb(x) cout<<#x" = "<<x<<endl
	#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
	char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
	class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &x)
	{
		register type s = 0; register int f = 1; register char ch = gc();
		while(!isdigit(ch)) {if(ch == '-') f = -1; ch = gc();}
		while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch  xor 48),ch = gc(); return x = s * f,*this;
	}}io;
}
#define int long long
using namespace xin_io; static const int maxn = 1e7+10,inf = 1e9+10,llinf = 1e18+10;
namespace xin
{	
	const int mod = 998244353;
	auto ksm = [](int x,int y,int mod,int ret = 1) -> int
	{
		while(y)
		{
			if(y & 1) ret = ret *x % mod;
			x = x * x % mod; y >>= 1;
		}
		return ret;
	};
	int id,T,c,p[maxn],n,m;
	inline short main()
	{
		file(division);	
		io >> id >> T;
		while(T--)
		{
			io >> c >> m; n = 1;
			try(i,1,c) io >> p[i];
			int ans = 1;
			try(t,1,c)
				(ans *= std::__gcd(m - 1,p[t] - 1) + 1) %= mod;
			printf("%lld\n",ans);
		}
		return 0;
	}
}
signed main() {return xin::main();}

糖果

考虑一个倍增 \(dp\)

\[dp[i][l][j]=(dp[i][l][j]+dp[i][l-1][j-k]*dp[i][l-1][k]\%mod*fac[j] \]


#include<bits/stdc++.h>
using std::cout; using std::endl;
#define int long long
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register int i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
	#define file(x) FILE *FI = freopen(#x".in","r",stdin); FI = freopen(#x".out","w",stdout);
	#define debug cout<<"debug"<<endl
	#define jb(x) cout<<#x" = "<<x<<endl;=
	#define sb(x) cout<<#x" = "<<x<<' '
	#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
	#define scanf ak = scanf
	char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
	class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &x)
	{
		register type s = 0; register int f = 1; register char ch = gc();
		while(!isdigit(ch)) {if(ch == '-') f = -1; ch = gc();}
		while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch  xor 48),ch = gc(); return x = s * f,*this;
	}}io;
}
using namespace xin_io; static const int maxn = 1e7+10,maxm = 101,inf = 1e9+7; const ll llinf = 1e18+7;
namespace xin
{
	const int mod=998244353;
	int n,m,a[maxn],A,B,P;
	int pos[maxn],he[maxm],dp[maxm][maxm][maxm],f[maxm][maxm][maxm];
	int ans[maxm][maxm],pre[maxm];
	int fac[maxm],inv[maxm];
	auto ksm = [](int x,int y,int ret = 1) -> int
	{
		while(y)
		{
			if(y & 1) ret = ret * x % mod; 
			x =  x * x % mod; y >>= 1;
		}
		return ret;
	};
	signed main()
	{
		file(sugar);
		io >> n >> m >> a[1] >> A >> B >> P;
		pos[a[1]]=1;
		try(i,2,n)
		{
			a[i] = (a[i-1] * A + B) % P + 1;
			if(pos[a[i]])
			{
				int temp = (n - pos[a[i]]+1) / (i-pos[a[i]]);
				int sheng = (n - pos[a[i]]+1) % (i-pos[a[i]]);
				try(j,pos[a[i]],i-1) {if(a[j]>m)a[j] = m;he[a[j]]++;}
				try(j,1,m) he[j] *= temp;
				try(j,pos[a[i]],pos[a[i]]+sheng-1) he[a[j]]++;
				try(j,1,pos[a[i]]-1) {if(a[j]>m)a[j] = m;he[a[j]]++;}
				break;
			}
			pos[a[i]]=i;
		}
		if(a[1] > m or !he[a[1]])
			try(i,1,n)
			{
				if(a[i] > m)a[i] = m;
				he[a[i]]++;
			}
		fac[0] = 1; try(i,1,m) fac[i] = fac[i-1]*i%mod;
		inv[0] = 1;
		inv[m]=ksm(fac[m],mod-2);
		throw(i,m-1,1) inv[i] = inv[i+1] * (i+1)%mod;
		try(i,1,m)
		{
			if(!he[i]){f[i][pre[i]][0]=1;continue;}
			try(j,0,i)dp[i][0][j]=1;
			try(l,1,62)try(j,0,m)try(k,0,j)dp[i][l][j]=(dp[i][l][j]+dp[i][l-1][j-k]*dp[i][l-1][k]%mod*fac[j]%mod*inv[j-k]%mod*inv[k])%mod;
			int temp=he[i];
			f[i][0][0]=1;
			throw(l,62,0)
			{
				if((1ll<<l) > temp) continue;
				temp -= (1ll << l);
				pre[i]++;
				try(j,0,m)
					try(k,0,j)
						f[i][pre[i]][j] = (f[i][pre[i]][j]+f[i][pre[i]-1][j-k]*dp[i][l][k]%mod*fac[j]%mod*inv[j-k]%mod*inv[k])%mod;
			}
		}
		ans[0][0] = 1;
		try(i,1,m)try(j,0,m)try(k,0,j)ans[i][j]=(ans[i][j]+ans[i-1][j-k]*f[i][pre[i]][k]%mod*fac[j]%mod*inv[j-k]%mod*inv[k])%mod;
		cout<<ans[m][m]<<endl;
		return 0;
	}
}
signed main() {return xin::main();}

打字机

这个东西比较麻烦。

如果单单是编辑距离那个题目的话那么一个简单的转移就行

这个我们则需要分段函数来处理

\(h_i\)\(s\) 的后缀的编辑距离,然后我们发现 \(i-h_i\) 一定是单调递增的。

然后我们第三位就可以放一个这个

\[ f[now][j][k + zhuan] = std::min(f[now xor 1][j][k + zhuan] + 1 , f[now][j][k + zhuan]);\\ f[now xor 1][j + 1][k + zhuan - 1] = std::min(f[now xor 1][j][k + zhuan] , f[now xor 1][j+1][k + zhuan - 1]);\\ f[now][j + 1][k + zhuan + (s[i+1] == t[j+1])] = std::min(f[now xor 1][j][k + zhuan] + 1 , \\f[now][j + 1][k + zhuan + (s[i+1] == t[j+1])]);\\ \]



#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register int i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
	#define file(a) FILE *FI = freopen(#a".in","r",stdin); FI = freopen(#a".out","w",stdout);
	#define debug cout<<"debug"<<endl
	#define sb(x) cout<<#x" = "<<x<<' '
	#define jb(x) cout<<#x" = "<<x<<endl
	#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
	char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
	class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &x)
	{
		register type s = 0; register int f = 1; register char ch = gc();
		while(!isdigit(ch)) {if(ch == '-') f = -1; ch = gc();}
		while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch  xor 48),ch = gc(); return x = s * f,*this;
	}}io;
	#define scanf ak = scanf
}
#define int long long
using namespace xin_io; static const int maxn = 1e6+10,two = 101,inf = 1e9+10,llinf = 1e18+10;
namespace xin
{
	int f[2][two][two];
	int g[maxn][two];
	char s[maxn],t[maxn];
	int l1,l2;

	int zhuan;

	auto prework = []() -> void
	{
		try(i,0,l2) 
		{
			try(k,-i,l2) f[0][i][k + zhuan] = inf;
			try(k,-l2-1,-i-1) f[0][i][k + zhuan] = -1;
		}
		f[0][0][zhuan] = 0;
		try(i,0,l1)
		{
			int now = (i & 1) xor 1;
			try(j,0,l2)
			{
				try(k,-j,l2) f[now][j][k + zhuan] = inf;
				try(k,-l2-1,-j-1) f[now][j][k + zhuan] = -1;
			}
			try(j,0,l2)
				try(k,-l2-1,l2)
				{
					f[now][j][k + zhuan] = std::min(f[now xor 1][j][k + zhuan] + 1 , f[now][j][k + zhuan]);
					f[now xor 1][j + 1][k + zhuan - 1] = std::min(f[now xor 1][j][k + zhuan] , f[now xor 1][j+1][k + zhuan - 1]);
					f[now][j + 1][k + zhuan + (s[i+1] == t[j+1])] = std::min(f[now xor 1][j][k + zhuan] + 1 , f[now][j + 1][k + zhuan + (s[i+1] == t[j+1])]);
				}
			try(k,-l2,l2)
				g[i][k + zhuan] = f[now xor 1][l2][k + zhuan];//,jb(g[i][k + zhuan]);
		}
	};


	auto getans(int l,int r) -> int
	{
		try(k,-l2,l2)
			if(g[r][k + zhuan] >= r - l + 1)
				return r - l + 1 - k;
		return 0;
	};


	inline short main()
	{
		file(print);

		scanf("%s%s",s+1,t+1);
		l1 = strlen(s + 1); l2 = strlen(t + 1);
		zhuan = l2 + 1;


		prework();


		int qnum;
		scanf("%lld",&qnum);
		while(qnum--)
		{
			register int l,r; io >> l >> r;
			printf("%lld\n",getans(l,r));
		}
		return 0;
	}
}
signed main() {return xin::main();}
posted @ 2021-09-25 20:25  NP2Z  阅读(27)  评论(0编辑  收藏  举报