[考试总结]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();}