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;
}
posted @   Steven1013  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示