[bzoj5043]密码破译
2017-09-23 22:01
267 查看
题目大意
有一个n个数的数组a和一个非负整数k(a[],k未知),但是你知道数组b,对于任意i满足bi=ai^k。你还知道∑ai=m求可能最小的k,无解输出-1n≤100000,bi≤260
分析
其实这种题都是套路题。首先可以预处理cnt[i]表示b数组有几个数二进制第i位为1,p[i]表示m的二进制第i位是否为1。然后从高到低逐位确定k。设f[i][j]表示确定到二进制第i位,只考虑从高到低前i位m还有2i∗j没有被减掉。然后对于k取0或1,第二维会分别变成2* j+p[i]-cnt[i],2*j+p[i]-n+cnt[i]。考虑第二维的大小,从二进制第i位到第0位,假设a全填1,它的和就等于∑ij=0n∗2i∗2j2i=2n∗2i−1,所以第二维有用的大小是2n。这足以通过此题
#include <cstdio> #include <cstring> #include <algorithm> #define min(a,b) ((a)<(b)?(a):(b)) using namespace std; const int N=2e5+5; typedef long long LL; int n,cnt[60],M[60],x,y; const LL Inf=1ll<<60; LL a ,f[2] ,m; int main() { scanf("%d%lld",&n,&m); for (int j=0;j<60;j++,m>>=1) M[j]=(m&1); for (int i=1;i<=n;i++) { scanf("%lld",&a[i]); for (int j=0;j<60;j++,a[i]>>=1) cnt[j]+=(a[i]&1); } memset(f[0],127,sizeof(f[0])); y=1; f[0][0]=0; LL p=1ll<<59; for (int i=59;i>=0;i--,p>>=1,x^=1,y^=1) { memset(f[y],127,sizeof(f[y])); for (int j=0;j<N;j++) if (f[x][j]<Inf) { int k=j*2+M[i]-cnt[i]; if (k>=0 && k<N) f[y][k]=min(f[y][k],f[x][j]); k=j*2+M[i]-n+cnt[i]; if (k>=0 && k<N) f[y][k]=min(f[y][k],f[x][j]+p); } } if (f[x][0]>=Inf) printf("-1\n");else printf("%lld\n",f[x][0]); return 0; }
相关文章推荐
- bzoj 5043: 密码破译
- bzoj5043: 密码破译
- [Bzoj5043][Lydsy1709月赛]密码破译(按位dp)
- BZOJ 5043: 密码破译 dp
- bzoj5043 密码破译
- [数学]bzoj5043密码破译
- bzoj 5043 密码破译 dp
- 三堂课,破译企业生存密码
- C语言实现密码破译
- BZOJ4327 玄武密码 (AC自动机)
- 河南省第一届程序设计竞赛___试题三 密码破译
- bzoj3325 [Scoi2013]密码(manacher构造题)
- L - 破译密码 有关字符串的处理
- 维吉尼亚密码加密过程图解及其破译方法
- 史上八大无法破译的密码
- 史上最牛玩家 数学+密码学破译隐藏任务
- BZOJ-4327:JSOI2012 玄武密码(AC自动机模板题)
- 使用MD5变换算法防穷举破译密码
- HDU1287 破译密码
- 破译电脑密码方法