暴力枚举每一位是否进位,然后就可以高斯消元解出方程了。然而复杂度是O(2nn3),相当不靠谱。

  考虑优化。注意到某一位进位情况的变化只会影响到方程的常数项,于是可以在最开始做一次高斯消元算出每个未知数与每个常数项的关系。这样就变成了O(2nn2),虽然仍然不靠谱不过经常可以早早break,就能过了。

  似乎有一些挺麻烦的地方怎么都调不对,后来就变成了面向代码编程也不知道改了什么最后几乎全一样了才过。事实上还是有bug的,比如2 AB BA AA这样的数据会re掉,原因是方程看似解不出来但是有所有数不同的限制,应该还要特判一下然而懒得写了。
  当然这本来是个剪枝题。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 30
int n,m,a[N],b[N],c[N],f[N][N],d[N][N],u[N];
bool flag[N];
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
void gauss()
{
for (int i=;i<=n;i++) d[i][i-]=-,d[i][i]=n;
for (int i=;i<=n;i++)
f[i][c[i]]--,f[i][a[i]]++,f[i][b[i]]++;
for (int i=,t=;i<=n&&t<=n;i++,t++)
{
int mx=i;
for (int j=i+;j<=n;j++)
if (abs(f[j][t])>abs(f[mx][t])) mx=j;
if (mx!=i) swap(f[i],f[mx]),swap(d[i],d[mx]);
if (!f[i][t]) {i--;continue;}
for (int j=;j<=n;j++)
if (i!=j&&f[j][t])
{
int x=f[j][t]/gcd(f[j][t],f[i][t]),y=f[i][t]/gcd(f[j][t],f[i][t]);
for (int k=;k<=n;k++)
f[j][k]=f[j][k]*y-f[i][k]*x,
d[j][k]=d[j][k]*y-d[i][k]*x;
}
}
}
void print()
{
int a[N]={};
for (int i=;i<=n;i++)
{
for (int j=;j<=n;j++)
a[i]+=d[i][j]*u[j];
a[i]/=f[i][i];
}
for (int i=;i<=n;i++) cout<<a[i]<<' ';
exit();
}
void check()
{
memset(flag,,sizeof(flag));
for (int i=;i<=n;i++)
{
int x=;
for (int j=;j<=n;j++) x+=d[i][j]*u[j];
if (x%f[i][i]) return;
x/=f[i][i];
if (x<||x>=n||flag[x]) return;
flag[x]=;
}
print();
}
void dfs(int k)
{
if (k==n) check();
else u[k]++,dfs(k+),u[k]--,dfs(k+);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("calc.in","r",stdin);
freopen("calc.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read();
char ch=getchar();while (ch<'A'||ch>'Z') ch=getchar();
for (int i=;i<=n;i++) m=max(m,a[i]=ch-'A'+),ch=getchar();
while (ch<'A'||ch>'Z') ch=getchar();
for (int i=;i<=n;i++) m=max(m,b[i]=ch-'A'+),ch=getchar();
while (ch<'A'||ch>'Z') ch=getchar();
for (int i=;i<=n;i++) m=max(m,c[i]=ch-'A'+),ch=getchar();
reverse(a+,a+n+),reverse(b+,b+n+),reverse(c+,c+n+);
gauss();
dfs();
return ;
}

Luogu1092 NOIP2004虫食算(搜索+高斯消元)的更多相关文章

  1. [BZOJ1902]:[NOIP2004]虫食算(搜索)

    题目传送门 题目描述 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母. 来看一个简单的例子: 43#98650#45+8468#6633=444455069 ...

  2. NOIP2004 虫食算

    描述 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子:43#9865#045+ 8468#6633= 44445506678其中#号代表 ...

  3. [题解](折半搜索/高斯消元枚举自由元)BZOJ_1770_Lights

    状压,时间空间都不行,如果每次搜索一半就可以省下很多空间,用map记下每种状态的答案,最后再把两次的答案合并 然而正解是高斯消元解异或方程组,最后搜索自由元 #include<iostream& ...

  4. [Noip2004]虫食算 dfs

    搜索问题的关键:优秀的搜索策略以及行之有效的减枝 对于这道题我们阶乘搜肯定不行所以我们按位搜,我们对每一位的三个数进行赋值,然后判解. 对于此一类的搜索乘上一个几十的常数来减枝往往要比直接搜要快得多, ...

  5. P1092 虫食算[搜索]

    这个式子是是由\(A\sim A+N\)组成的,那么\(A\sim A+N\)就只能等于\(0\sim N-1\),因此我们每次对\(A\sim A+N\)的取值做一个新的排列,然后judge一下当前 ...

  6. VIJOS 1052贾老二算算术 (高斯消元)

    描述 贾老二是个品学兼优的好学生,但由于智商问题,算术学得不是很好,尤其是在解方程这个方面.虽然他解决 2x=2 这样的方程游刃有余,但是对于 {x+y=3 x-y=1} 这样的方程组就束手无策了.于 ...

  7. NOIP 2004 虫食算题解

    问题 E: [Noip2004]虫食算 时间限制: 1 Sec  内存限制: 128 MB 题目描述 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一 ...

  8. 【算法】高斯消元&线性代数

    寒假作业~就把文章和题解3道题的代码扔在这里啦——链接: https://pan.baidu.com/s/1kWkGnxd 密码: bhh9 1.HNOI2013游走 #include <bit ...

  9. [NOIP2004] 提高组 洛谷P1092 虫食算

    题目描述 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045 +8468#6633 44445509678 其中# ...

随机推荐

  1. 北京Uber优步司机奖励政策(2月7日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  2. 如何理解 UL94HB , UL94-V0 , UL94-V1 , UL94-V2

    塑料阻燃等级由HB,V-2,V-1向V-0逐级递增: UL94V0,V1,V2是不同的阻燃等级,其等级不同,耐燃的测试方法亦不同,测试判定的标准也不同. V0的测试方法是将测试物倾斜45度,用酒精灯点 ...

  3. MySQL高级-慢查询日志

    一.慢查询日志是什么 1. 2. 3. 2.开启了慢查询日志后,什么样的SQL才会记录到慢查询日志里面呢? 3.案例 1.查看当前多少秒算慢 2.设置慢的阙值时间 3.为什么设置后看不出变化? 4.记 ...

  4. Andorid自定义attr的各种坑

    本文来自网易云社区 作者:孙有军 在开发Andorid应用程序中,经常会自定义View来实现各种各样炫酷的效果,在实现这吊炸天效果的同时,我们往往会定义很多attr属性,这样就可以在XML中配置我们想 ...

  5. Python对象引用问题总结

    对于对象引用问题,一直是一知半解的状态,现整理以备使用. 操作不可变对象进行加减运算时,会在内存中创建新的不可变实例,不会影响原来的引用>>> c=12>>> d= ...

  6. adb获取设备的序列号

    用数据线连接手机, 打开开发者模式, 并赋予相关权限, 在CMD命令行输入: adb devices 第一个参数即为设备的序列号, 第二个参数device表示设备的状态是在线.

  7. 感觉总结了一切python常见知识点,可直接运行版本

    #encoding=utf-8#http://python.jobbole.com/85231/#作用域a=1def A(a): a=2 print 'A:',a def B(): print 'B: ...

  8. 软件测试的基础-摘自《selenium实践-基于电子商务平台》

    软件测试的方法 一.等价类划分法 等价类划分法是把所有可能的输入数据,即程序的输入域划分成若干部分(子集),然后从每一个子集中选取少量具有代表性的数据作为测试用例. 有两种不同的情况:有效等价和无效等 ...

  9. 百度翻译api 实现简易微信翻译小程序

    介绍 口袋翻译 口袋翻译 微信小程序 翻译功能 含7类语言的相互翻译 包含最近10条的翻译历史回溯功能 微信搜索:简e翻译 功能展示   使用百度翻译api需要申请 appid 与 key 并在 ap ...

  10. Linux系统负载查询

    查询Linux系统负载情况,一般需要了解三个方面的信息: 1.Linux系统配置.如Linux版本号.CPU.内存.网络.磁盘等: 2.收集系统负载信息的手段.常用的工具包有sysstat和procp ...