http://acm.hdu.edu.cn/showproblem.php?pid=6129

【题意】

  • 对于一个长度为n的序列a,我们可以计算b[i]=a1^a2^......^ai,这样得到序列b
  • 重复这样的操作m次,每次都是从上次求出的序列a得到一个新序列b
  • 给定初始的序列,求重复m次操作后得到的序列

【方法一】

假定n=5,我们模拟一次可以发现,经过m次操作后a1在b1......bn中出现的次数为:

  • m=0: 1 0 0 0 0
  • m=2: 1 2 3 4 5
  • m=3: 1 3 6 10 15
  • m=4:1 4 10 20 35
  • m=5:1 5 15 35 70

(画个杨辉三角出来就可以看出这些都是组合数)

容易推出来操作m次后,a1在答案bi中出现的次数C(m+i-2,m-1),由于是异或,我们只需知道C(m+i-2,m-1)%2

根据Lucas定理(2是素数),x=m-1,y=m+i-2,C(x,y)%2为x和y写成二进制后每一位C(xi,yi)%2的连乘,可以发现,只有C(0,1)是0,也就是C(x,y)%2==0  <=> y的二进制位置为1的集合是x的子集 <=> (x&y)==y

这道题m=1的时候是n^2的,然而这个复杂度是可以过的(奇怪)

附上AC代码

【AC】

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+;
ll a[maxn];
ll b[maxn];
int n;
ll m;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(b,,sizeof(b));
scanf("%d%I64d",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%I64d",&a[i]);
}
for(int i=;i<=n;i++)
{
ll y=m-;
ll x=m+i-;
if((x&y)==y)
{
for(int j=i;j<=n;j++)
{
b[j]^=a[j-i+];
}
}
}
for(int i=;i<=n;i++)
{
if(i==) printf("%I64d",b[i]);
else printf(" %I64d",b[i]);
}
puts("");
}
return ;
}

【经验】

  • 把a,b二进制表达后b中1的位置是a中1的位置的子集    <=> (a&b)==b
  • C(2^k-1,i)%2==1                     <=>               0<=i<=2^k-1

********************************************************************************************************************************

【方法二】

dp(i, j)表示第i次变换第j列的数。 
dp(i, j) = dp(i, j-1)^dp(i-1, j) = dp(i, j-2)^dp(i-1, j-1)^dp(i-1, j-1)^dp(i-2, j) = dp(i, j-2)^dp(i-2, j) => dp(i, j-2^n)^dp(i-2^n, j) 
从m中的最高位或最低位开始递推。

类似于dp[i][j]=dp[i-1][j]+dp[i][j-1],最后求dp[m][j](1<=j<=n)我们可以开一个滚动数组从前往后递推(dp[i][j]=dp[i-1][j]+dp[i][j+1]则是从后往前推)

 for(int i=;i<=m;i++)
{
for(int j=;j<=n;j++)
{
dp[j]^=dp[j-];
}
}

dp[i][j]=dp[i-1][j]^dp[i][j-1]

计算dp[i][j]=dp[i-2^n][j]^dp[i][j-2^n],用lowbit从右往左枚举m的每一位,每一次都对整列进行更新。

 while(m)
{
int x=lowbit(m);
for(int j=x;j<=n;j++)
{
dp[j]^=dp[j-x];
}
m-=x;
}

dp[i][j]=dp[i-2^n]^dp[i][j-2^n]

【AC】

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+;
int n,m;
int dp[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=;i<n;i++)
{
scanf("%d",&dp[i]);
}
while(m)
{
int x=m&(-m);
for(int i=x;i<n;i++)
{
dp[i]^=dp[i-x];
}
m-=x;
}
for(int i=;i<n;i++)
{
if(i==) printf("%d",dp[i]);
else printf(" %d",dp[i]);
}
puts("");
}
return ;
}

递推+lowbit+滚动数组

***********************************************************************************************************************************

【方法三】

http://m.blog.csdn.net/silence255713/article/details/77200056

【(好题)组合数+Lucas定理+公式递推(lowbit+滚动数组)+打表找规律】2017多校训练七 HDU 6129 Just do it的更多相关文章

  1. 51nod 1126 - 求递推序列的第N项 - [找规律]

    题目链接:https://cn.vjudge.net/problem/51Nod-1126 有一个序列是这样定义的:f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + ...

  2. 递推:Number Sequence(mod找规律)

    解题心得: 1.对于数据很大,很可怕,不可能用常规手段算出最后的值在进行mod的时候,可以思考找规律. 2.找规律时不必用手算(我傻,用手算了好久).直接先找前100项进行mod打一个表出来,直接看就 ...

  3. 【组合数+Lucas定理模板】HDU 3037 Saving

    acm.hdu.edu.cn/showproblem.php?pid=3037 [题意] m个松果,n棵树 求把最多m个松果分配到最多n棵树的方案数 方案数有可能很大,模素数p 1 <= n, ...

  4. HYSBZ(BZOJ) 4300 绝世好题(位运算,递推)

    HYSBZ(BZOJ) 4300 绝世好题(位运算,递推) Description 给定一个长度为n的数列ai,求ai的子序列bi的最长长度,满足bi&bi-1!=0(2<=i<= ...

  5. uoj86 mx的组合数 (lucas定理+数位dp+原根与指标+NTT)

    uoj86 mx的组合数 (lucas定理+数位dp+原根与指标+NTT) uoj 题目描述自己看去吧( 题解时间 首先看到 $ p $ 这么小还是质数,第一时间想到 $ lucas $ 定理. 注意 ...

  6. Nowcoder 练习赛 17 C 操作数 ( k次前缀和、矩阵快速幂打表找规律、组合数 )

    题目链接 题意 :  给定长度为n的数组a,定义一次操作为: 1. 算出长度为n的数组s,使得si= (a[1] + a[2] + ... + a[i]) mod 1,000,000,007: 2. ...

  7. luogu4345 [SHOI2015]超能粒子炮·改(组合数/Lucas定理)

    link 输入\(n,k\),求\(\sum_{i=0}^k{n\choose i}\)对2333取模,10万组询问,n,k<=1e18 注意到一个2333这个数字很小并且还是质数这一良好性质, ...

  8. 【BZOJ-4591】超能粒子炮·改 数论 + 组合数 + Lucas定理

    4591: [Shoi2015]超能粒子炮·改 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 95  Solved: 33[Submit][Statu ...

  9. 组合数(Lucas定理) + 快速幂 --- HDU 5226 Tom and matrix

    Tom and matrix Problem's Link:   http://acm.hdu.edu.cn/showproblem.php?pid=5226 Mean: 题意很简单,略. analy ...

随机推荐

  1. [总结].net操作MongoDb通用基础类1:

    public class MongoDBHelper { //定义Mongo服务 private MongoServer mongo = null; //获取databaseName对应的数据库,不存 ...

  2. MFC技术积累——基于MFC对话框类的那些事儿

    1. 创建对话框类 (1)打开VC++6.0环境,点击:文件→新建: (2)在弹出的新建对话框中选择:工程→MFC AppWizard (exe)→输入工程名称(例如:功能调试)→工程保存路径名→确定 ...

  3. Caused by: java.lang.NoClassDefFoundError: com/sun/tools/javac/util/List at

    折腾了一下的时间,都没有找到解决的方案,在网上搜了一下答案都是让清理编译环境和重新打包之类的.就这样折腾一下,还没有解决问题.之所以会抛出找不到类的问题,需要排查你使用这个包的类是否存在,存在之后 查 ...

  4. 系统报错undefine not symbol armv7

    libz.dylib libsqlite3.dylib libstdc++.dylib 添加这些动态链接库

  5. Shell脚本之for循环、while循环,if语句、case语句

    1. for循环一般格式: 格式1: for((条件)) do 动作 done 格式2: for 变量名 in 范围 do 动作 done1234567891011121314实验:##1. 输出数字 ...

  6. javascript单元测试框架mochajs详解(转载)

    章节目录 关于单元测试的想法 mocha单元测试框架简介 安装mocha 一个简单的例子 mocha支持的断言模块 同步代码测试 异步代码测试 promise代码测试 不建议使用箭头函数 钩子函数 钩 ...

  7. 如何移除 Navicat Premium for Mac 的所有文件

    作者:郭文峰链接:http://www.zhihu.com/question/24210959/answer/34579422来源:知乎著作权归作者所有,转载请联系作者获得授权. 数据库连接信息存放在 ...

  8. linux or msys2设置网络代理

    在文件 .bashrc 中添加 export http_proxy="proxy IP:port" 如 export http_proxy="192.168.0.1:80 ...

  9. CAP 可用性理解

    从容灾角度看可用性. 多机同时返回. 主通过 heart-beat 脑裂. 用 paxos. 性能远距离. 对整体压力较大. 从用户体验的角度看单数据可用性: 不考虑城市灾备的情况发生.只有单机房的 ...

  10. shell脚本,如何监控目录下的文件内容是否被修改。

    第一种方法是通过cmp来进行比对[root@localhost bo]# ls .html .html .html .html .html .html .html .html .html cat.sh ...