UOJ#267 BZOJ4731【清华集训2016】魔法小程序

本文介绍了一种实现任意进制FWT逆变换的方法,通过将序列分组并递归处理来解决特定问题。文章提供了完整的C++代码示例。

UOJ终于把清华集训的题加上辣!BZOJ上数据还是错的,之前写完代码都没地方交

题意就是让你做任意进制的FWT的逆变换

类比二进制容易得到在k进制下的做法:把整个序列分成k段,分别递归处理剩余位的影响后考虑这一位的影响即可

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<queue>
#include<stack>
using namespace std;
#define MAXN 1000010
#define MAXM 1000010
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-8
#define ll long long
int n,m;
int M=1;
int a[MAXN];
ll c[MAXN];
ll len[MAXN];
int tot;
int L[MAXN],R[MAXN];
int ta[MAXN];
void cal(int l,int r,int d){
	int i,j;
	if(!d){
		return ;
	}
	int t=0;
	int lst=l;
	for(i=l;i<=r;i++){
		t++;
		if(t==len[d-1]||i==r){
			cal(lst,i,d-1);
			lst=i+1;
			t=0;
		}
	}
	t=0;
	lst=l;
	tot=0;
	for(i=l;i<=r;i++){
		t++;
		if(t==len[d-1]||i==r){
			tot++;
			L[tot]=lst;
			R[tot]=i;
			lst=i+1;
			t=0;
		}
	}
	for(i=tot;i>1;i--){
		for(j=L[i];j<=R[i];j++){
			c[j]-=c[j-len[d-1]];
		}
	}
}
int main(int argc,char *argv[]){
	int i;
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	int tn=0;
	for(i=1;i<=n;i++){
		if(a[i]!=1){
			ta[++tn]=a[i];
		}
	}
	scanf("%d",&m);
	ta[tn+1]=m;
	for(i=1;i<=m;i++){
		scanf("%lld",&c[i]);
	}
	len[0]=1;
	for(i=1;i<=tn+1;i++){
		len[i]=len[i-1]*ta[i];
		if(len[i]>=m){
			cal(1,m,i);
			break;
		}
	}
	printf("%d\n",n);
	for(i=1;i<=n;i++){
		printf(i==n?"%d\n":"%d ",a[i]);
	}
	printf("%d\n",m);
	for(i=1;i<=m;i++){
		printf(i==m?"%lld\n":"%lld ",c[i]);
	}
	return 0;
}

/*

*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值