hihocoder 1166 期望dp+高斯消元

本文介绍了一个基于交换代数概念的小游戏。游戏中有n个球,初始状态为黑白两色混合,玩家通过随机选择区间反转颜色的方式,试图将所有球变为白色。文章提供了计算期望反转次数的算法,并附带代码实现。

#1166 : 交换代数

时间限制:20000ms
单点时限:1000ms
内存限制:256MB

描述

少女幽香这几天正在学习交换代数,然而她什么也没有学会,非常痛苦。于是她开始玩起了一个简单的小游戏,来放松一下。
地面上一共有n个球,一开始有一些是黑色的,有一些是白色的。每次她随机选择一个区间(一共有n(n+1)/2个区间,每个区间有相等的概率被选择),把这个区间的颜色反转,即将该区间中白球变黑球,黑球变白球。
现在她想要知道期望情况下,多少次反转能够使得整个区间都是白色的。

输入

第一行n (1 <= n <= 20),表示球的数量。
接下来一行n个数,表示这些球的颜色,0表示白色,1表示黑色。

输出

一行一个实数,表示答案。你的答案与标准答案的绝对误差在10-4以内就算正确。

样例输入
2
0 1
样例输出
3.000000
#include <iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#define eps 1e-9
using namespace std;
int b[25];
int d[25];
double a[25][25];
double x[25];
int n;
double Gauss()
{
    int row, col, max_r;
    int equ,var;
    equ = var = n;
    row = col = 0;
    while(row < equ && col < var)
    {
        max_r = row;
        for(int i = row+1; i < equ; i++)
            if(fabs(a[i][col])-fabs(a[max_r][col]) > eps)
                max_r = i;
        if(max_r != row)
            for(int j = col; j <= var; j++)
                swap(a[row][j], a[max_r][j]);
        if(fabs(a[row][col]) < eps)
        {
            col++;
            continue;
        }
        for(int i = row+1; i < equ; i++)
        {
            if(fabs(a[i][col]) > eps)
            {
                double t = a[i][col]/a[row][col];
                a[i][col] = 0.0;
                for(int j = col+1; j <= var; j++)
                    a[i][j] -= a[row][j]*t;
            }
        }
        row++;
        col++;
    }
    for(int i = equ-1; i >= 0; i--)
    {
        if(fabs(a[i][i]) < eps) continue;
        double tmp = a[i][var];
        for(int j = i+1; j < var; j++)
            tmp -= a[i][j]*x[j];
        x[i] = tmp/a[i][i];
    }
}
int main()
{
    while(cin>>n)
    {
    for(int i=1;i<=n;i++)
        cin>>b[i];
    b[0]=0;b[n+1]=0;
    int ans=0;
    for(int i=0;i<=n;i++)
      {
          d[i]=b[i]^b[i+1];
          if(d[i]==0)
            ans++;
      }
      memset(d,0,sizeof(d));
      memset(a,0,sizeof(a));

      //dp[m]=m(m-1)/n(n-1)*dp[m-2]+(n-m)(n-m-1)/n(n-1)*dp[m+2]+2*m(n-m)/n(n-1)*dp[m]+1
      n=n+1;//0-N 所以个数为n+1
    for(int i=0;i<n;i++)
    {
         a[i][i]=1.0-2.0*i*(n-i)/(n*(n-1)*1.0);
         if(i>=2)
         a[i][i-2]=-(i*(i-1))/((n*(n-1))*1.0);
         if(i<n-2)
         a[i][i+2]=-(n-i)*(n-i-1)/(n*(n-1)*1.0);
         a[i][n]=1;
    }
    Gauss();
    printf("%lf\n",x[ans]);
    }
    return 0;


}

内容概要:本文详细记录了对一个Android ARM64静态ELF文件中字符串加密机制的逆向分析过程。该ELF文件的所有字符串均被加密,无法通过常规strings命令或IDA直接识别。作者通过分析发现,加密字符串存储在.rodata段,其解密所需信息(包括密文地址、长度和16位密钥)保存在.data.rel.ro段的40字节描述符中。核心解密函数sub_10F408采用自反的双pass流密码算法,结合固定密钥KEY_TERM(由.data段24字节数据计算得出),实现字节级非线性、位置与长度相关的加密。文章还复现了完整的Python解密脚本,并揭示了该保护机制的本质为代码混淆而非强加密,最终成功批量解密全部956条字符串,暴露程序真实行为,如shell命令模板、设备标识篡改、网络重置等操作。此外,文中还提及未启用的自定义壳框架及其反dump设计。; 适合人群:具备逆向工程基础的安全研究人员、二进制分析人员及对ELF保护技术感兴趣的开发者。; 使用场景及目标:①学习ELF二进制中字符串加密的典型实现方式与逆向突破口;②掌握从结构识别、函数追踪到算法还原的完整逆向流程;③理解“绑定二进制”的完整性校验设计及其局限性;④实践编写IDAPython脚本自动化提取与解密敏感数据。; 阅读建议:此资源以实战案例驱动,不仅展示技术细节,更强调逆向思维与验证方法,建议读者结合IDA调试环境,逐步跟随文中步骤进行动态分析与算法验证,深入理解每一步的推理依据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值