2024.10.14 CW 模拟赛
T1 数组计数
题面
给定 \(n、k\),计算有多少个数列 \(a[1,2,...,n]\) 满足下列条件:
1.\(\forall i \in [1,k]\) ,有\(a[i]>0\).
2.\(\forall i \in [2,k]\) ,有 \(a[i] \ge \sum_{j=1}^{i-1} a[j]\)
3.$ \sum _{i=1}^k a[i]=n$
输出方案数对99824353取模的结果
SOLUTION
令 \(f_{i,j}\) 表示前 \(i\) 个数和为 \(j\) 的方案数,显然 \(2^{k-i}j \le n\) ,所以对于所有 \(i\) ,合法的 \(j\) 的数量是 \(O(n)\) 的,转移可以用前缀和优化,时间复杂度为 \(O(n)\) .
CODE
#include "bits/stdc++.h"
using namespace std;
#define int long long
#define FOR(i,j,k) for (int i=j;i<=k;i++)
#define ROF(i,j,k) for (int i=j;i>=k;i--)
#define mod(x) (x)%998244353
template<typename T>
inline void read(T &x){
bool f=1;x=0; char ch=getchar();
while (ch<'0' || ch>'9'){if (ch=='-') f=!f; ch=getchar();}
while(ch>='0' && ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
x=(f?x:-x);return;
}
template<typename T>
inline void write(T x){
if (x<0) putchar('-'),x=-x;
if (x>9) write(x/10);
putchar(x%10+'0');
return;
}
const int N=1e6+1;
int n,k,ans=0;
int f[N][21];
int sum[21];
signed main(){
read(n),read(k);
if (k==1) write(1);
else if (k==2) write(n>>1);
else{
FOR(i,1,k) f[0][i]=1;
FOR(i,1,k) sum[i]=(1<<i-1);
FOR(i,1,n) FOR(j,0,k){
if (i>=sum[j]) f[i][j]=mod(f[i][j-1]+f[i-sum[j]][j]);
else f[i][j]=mod(f[i][j]+f[i][j-1]);
}
write(f[n-sum[k]][k]);
}
return 0;
}
T4 进化
题面
小 A 有一个数组 \(a[1..n]\) ,(保证 \(n \ge 2\) ) ,其中 \(a[i] \in \{0,1\}\) ,但是这个数组在被创建后就被小 A 扔在一旁了。
然而数组是很上进的,他不像人类一样每天不思进取,数组每天是会进化的。
定义一个数组 \(a[1..n]\) 经过一次进化后变成的数组是 \(b[1..n]\) ,其中:
\(b[1] = a[2]\)
\(b[n]=a[n-1]\)
\(b[i]=(a[i-1]a[i+1]) \bmod 2\) (其中 \(2 \le i <n\) )
现在小 B 想知道,这个数组进化 T 次后是什么样的。
SOLUTION
观察式子:
\(\begin{cases} b[i] = a[i+1] & i=1 \\ b[i] = (a[i+1]+a[i-1]) \bmod 2 & 2 \le i < n \\ b[i]=a[i-1] & i=n \end{cases} \\\)
发现难以找出规律,因为并没有一个通项公式可以得出每一项,所以考虑将其增添为一个无限的数列,使得其中每一个数都满足 \(b[i]=(a[i-1]+a[i+1]) \bmod 2 (\leftrightarrow a[i-1] \oplus a[i+1]).\) 不难发现若在 \(a[1]\) 和 \(a[n]\) 前后均添上一个 \(0\) 便可使得其满足该通项公式,同理,欲使得两侧的 \(0\) 同样满足该通项公式,便需分别在左、右端加上 \(a[1],a[n]\) 构成数列 $...a[2],a[1],0,a[1],a[2],...,a[n],0,a[n],a[n-1]... $ 这样一个长度为 \((2n+2)\) 环(或者说是一个循环的序列)。
设这个环为 \(c\) ,将 \(c\) 进化 \(2^x\) 次变成 \(d\) ,考虑 \(d_i\) 的值。
容易发现进化的转移是类似杨辉三角的形式,而对于任意非负整数 \(x\) ,杨辉三角的第 \(2^x\) 行都只有 \(2\) 个奇数。
因此 \(d_i\) 实际上是 \(c\) 中两个数的和,即 $d_i=c_{i-2x}+c_{i+2x} $
时间复杂度 \(O(N \log T).\)
CODE
#include "iostream"
#include "cstring"
#define int long long
#define FOR(i,j,k) for (int i=j;i<=k;i++)
using namespace std;
const int N=2e5+10;
string s;
int t,n;
int c[N],d[N];
signed main(){
ios::sync_with_stdio(0);
cin.tie(nullptr);
cout.tie(nullptr);
cin >>t>>n;
cin >>s;
s=" "+s;
c[0]=c[n+1]=0;
FOR(i,1,n) c[i]=c[(n<<1|1)+1-i]=s[i]-'0';
int x=1,len=(n<<1|1)+1;
while (t){
if (t&1){
FOR(i,1,len) d[i]=c[((i-x)%len+len)%len]^c[(i+x)%len];
FOR(i,1,len) c[i]=d[i];
}
t>>=1;
x<<=1;
}
FOR(i,1,n) cout <<c[i];
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现