[BZOJ4731][UOJ#267]-魔法小程序-分治(FWT)思想

20人阅读 评论(0) 收藏 举报
分类:

说在前面

佩服那些用时短的提交……
(卡常失败蹲墙角


题目

BZOJ4731传送门
UOJ#267传送门

题目大意

现在定义了一种变换:
给出一个数组a[]和一个数组b[],其中a表示每一位的进制(如a[]=2,3,3表示,第一位2进制,第二位和第三位都是3进制)
变换:c[i]=b[j]  aji,其中b[]和c[]长度相同

现在给出a[]和c[],请输出一个合法的b[]
a的长度不超过1e4;b,c的长度不超过1e6;保证1e9内有解

输出输出格式

输入格式:
第一行一个整数M,表示a[]的长度
接下来一行M个正整数,表示a[]
第三行一个整数N,表示c[]的长度
接下来一行N个正整数,表示c[]

输出格式:
格式同上,第三、四行输出b[]


解法

其实就是一个按位分治的思想
如果理解了FWT,做这个题就很简单了
关于分治思想,可以参考me这一篇文章里的fast transform的部分,这里me就懒得打了….


下面是自带大常数的代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

int N , M , ws , remN ;
long long a[10005] , c[2000005] ;

void preWork(){
    int tmp = M + 1 ; M = 0 ;
    for( int i = 1 ; i <= tmp ; i ++ )
        if( a[i] > 1 ) a[++M] = a[i] ;
    int t = N ; ws = 1 ;
    while( true ){
        if( t < a[ws] ) break ;
        else t /= a[ws] , ws ++ ;
    } N = a[ws] = t + 1 ;
    for( int i = 1 ; i < ws ; i ++ ) N *= a[i] ;
}

void dfs( int lf , int rg , int w ){
    int siz = ( rg - lf + 1 ) / a[w] , i , j , ed ;
    for( i = a[w] - 1 , ed = rg ; i >= 0 ; i -- , ed -= siz ){
        if( i ) for( j = 0 ; j < siz ; j ++ )
            c[ed-j] -= c[ed-j-siz] ;
        if( w > 1 ) dfs( ed - siz + 1 , ed , w - 1 ) ;
    }
}

void solve(){
    dfs( 0 , N - 1 , ws ) ;
    printf( "%d\n" , remN ) ;
    for( int i = 0 ; i < remN ; i ++ ) printf( "%lld " , c[i] ) ;
}

template< typename T >
inline void read_( T &x ) {
    int fix = 1 ;
    x = 0 ; char ch = getchar() ;
    while( ch < '0' || ch > '9' ){
        if( ch == '-' ) fix = -1 ;
        ch = getchar() ;
    } while( ch >= '0' && ch <= '9' ) x = (x<<1) + (x<<3) + ch - '0' , ch = getchar() ;
    x *= fix ;
}

int main(){
    read_( M ) , printf( "%d\n" , M ) ;
    a[M+1] = 100000000 ;
    for( int i = 1 ; i <= M ; i ++ )
        read_( a[i] ) , printf( "%lld " , a[i] ) ;
    puts( "" ) ;
    read_( N ) , remN = N ;
    for( int i = 0 ; i < N ; i ++ ) read_( c[i] ) ;
    preWork() ; solve() ;
}
查看评论

UML参考手册 第二部分 基 本 概 念 第8章 交 互 视 图

UML参考手册  第二部分 基 本 概 念  第8章 交 互 视 图8.1 概述  对象间的相互作用体现了对象的行为。这种相互作用可以描述成两种互补的方式,一种以独立的对象为中心进行考察,另一种以互相...
  • CandyCat
  • CandyCat
  • 2001-05-26 23:02:00
  • 1324

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

UOJ终于把清华集训的题加上辣!BZOJ上数据还是错的,之前写完代码都没地方交 题意就是让你做任意进制的FWT的逆变换 类比二进制容易得到在k进制下的做法:把整个序列分成k段,分别递归处理剩余位的...
  • neither_nor
  • neither_nor
  • 2017-03-04 17:47:50
  • 870

[BZOJ4731][UOJ267]魔法小程序

先把代码读懂,可以理解成为c是b的高维前缀和 a[i]a[i]是第ii维的长度 显然长度大于1的维数不会超过log2(m)log_2(m) 暴力还原回b就行了#include #define ...
  • di4CoveRy
  • di4CoveRy
  • 2017-05-06 14:21:41
  • 294

【清华集训2016】魔法小程序

[UOJ267]【清华集训2016】魔法小程序 有这样一段魔法的程序:(其中所有的数组下标从 000 开始,所有的除法的结果为整数,且向 000 取整) 定义数组 ...
  • Effervescence
  • Effervescence
  • 2018-02-12 17:41:06
  • 58

UOJ 267 [清华集训2016]魔法小程序

前缀和非常认真地观察代码之后我们会发现实际上这是一个多维前缀和问题,c就记录前缀和。考虑前缀和的逆操作,即可复原出原数组。#include #define R register #define N 1...
  • ziqian2000
  • ziqian2000
  • 2017-03-06 17:13:36
  • 478

hdu5909 Tree Cutting - FWT 加速集合异或

http://acm.hdu.edu.cn/showproblem.php?pid=5909 问题描述 Byteasar有一棵nn个点的无根树,节点依次编号为11到nn,其中节点ii的权值为v...
  • viphong
  • viphong
  • 2016-10-02 18:44:15
  • 1988

TC srm518 Nim【动态规划+FWT】

题目大意:求符合以下条件的序列个数: 1:长度为K 2:每个元素大小不超过L 3:每个数都是质数 4:所有数异或和为0 K≤109,L≤50000K\le10^9,L\le 50000 ...
  • cdsszjj
  • cdsszjj
  • 2017-12-27 15:20:00
  • 110

学习笔记之递归和分治思想

递归,首先它的目的是把问题缩小为同类问题的子问题,通过不断地递归调用自身,最终到达某次调用能结束返回。 如果f()是一个递归函数,调用是这样的: 条件:递归到一定程度必须可以终止,不能无限...
  • xj2011xn
  • xj2011xn
  • 2015-11-27 17:29:24
  • 1131

快速排序基于分治法的思想

对于快速排序的自我小结: 关键在于伪代码的理解,这同样是采用了分治法的思想 #include using namespace std;//找到基准元素下标的函数 int FindPos(int arr...
  • zhang245754954
  • zhang245754954
  • 2016-09-13 17:39:51
  • 545

java面向对象 纸牌魔术小程序

  • 2014年04月12日 05:44
  • 6KB
  • 下载
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 2万+
    积分: 2187
    排名: 2万+
    博客专栏