出题人罗哲正是神爷 Orz

Description

  这是一道披着交互题外衣的通信题,只支持 C++。

  你需要实现 \(2\) 个函数。

  交互库先给第一个函数传入一个参数 \(n\),你加密得到的 \(01\) 字符串的长度必须是 $n。你需要根据 \(n\) 做一些相应的预处理,并向交互库返回你能接受的最大 \(\text{long long}\) 类型整数 \(m\)。

  先根据你返回的 \(m\) 给分。若 \(m_{you}\gt m_{ans}\) 则你得 \(0\) 分,若 \(m_{you}=m_{ans}\) 则你得 \(100\) 分,否则你得 \(0.5\frac{\ln{m_{sum}}}{\ln{m_{ans}}}\) 分。

  这题出到这里可以结束了。但出题人为了验证你的 \(m\) 是算的还是蒙的,又给了 \(Q\) 次操作,每次操作中:

    交互库向第一个函数输入一个 \([0,m-1]\) 内 \(\text{long long}\) 类型的数,你可以用任意加密手段,将该数加密成一个 \(n\) 位 \(01\) 字符串并返回给交互库。

    然后交互库向第二个函数输入你刚才加密得到的密串,这个密串有可能被交互库恶搞,导致该串所有位取反,然后整个串翻转。你需要用适当的解密手段,将其解密为一开始向第一个函数输入的 \(\text{long long}\) 类型的数,并返回给交互库。

    每次操作后,交互库会判断第二个函数返回的数 是否和一开始向第一个函数输入的数一样。

  一旦有一次操作加密前的数和解密后的数不一样,你就得不到解密分数,即之前根据 \(m\) 得的分数打折 \(20\%\)。

  有防作弊机制(即开全局变量记录原数),详见原题面。

  subtask1 (30pts):\(n\le 18\)

  subtask2 (70pts):\(n\le 60\)

  对于所有数据,\(0\le Q\le 50000\)

  

  由于交互题描述很长,我懒得一字不差地搬完,下面放上完整题面,但问题描述写得有点恶心,我一开始没看懂





Solution

  设 \(k\) 是长度为 \(n\) 且被恶搞后不变的串的数目。

  先考虑 \(n\) 是奇数的情况。

  显然翻转之后正中间的一个 bit 一定会取反,此时 \(k=0,\space m=2^{n-1}\)。编码方式也很简单,让正中间的 bit 为 \(0\),解码时若正中间的 bit 为 \(1\) 则执行恶搞操作。

  然后是(我)想不到的 \(n\) 是偶数的情况。

  不难算出 \(k=2^{\frac{n}{2}}\),因为一个串被恶搞后与原串相同,当且仅当这个 \(01\) 串的第 \(1\) 位与第 \(n\) 位不同,第 \(2\) 位与第 \(n-1\) 位不同,第 \(3\) 位与第 \(n-2\) 为不同,以此类推,共 \(\frac{n}{2}\) 组对称位。这些被恶搞后不变的串互不混淆,都可以作为密串

  对于其余所有被恶搞后有变化的串,一定是两两配对,共 \(\frac{2^n-2^{\frac{n}{2}}}{2}\) 对。每一对中我们只能使用一个数作为加密后的串,因为一对中的 \(2\) 个都选的话,万一交互库把你加密后的串恶搞了,你就无法区分这两种密串,也就不知道应该用哪种密串解密出原数。

  那么在密串长度为 \(n\) 的限制下,共有 \(2^{\frac{n}{2}} + \frac{2^n-2^{\frac{n}{2}}}{2} = 2^{n-1} + 2^{\frac{n}{2}-1}\) 种互不混淆的密串。

  神奇操作:我们可以把 \([0,m-1]\) 种所有整数一一映射到这些密串,故 \(m=2^{n-1} + 2^{\frac{n}{2}-1}\)。

  那我们怎么构造一种映射方式呢?

  我们肯定得从密串中抠出 \(1\) 或 \(2\) 位,来标记这个串是否被恶搞,不然肯定没法做。

  而且为了固定这个标记位,即被恶搞后不会翻转到对称位(你的第 \(2\) 个程序无法判断收到的密串的标记位有没有被翻到对称位,因为你只能通过标记位判断密串有没有翻转),若抠出 \(1\) 位,那么串长 \(n\) 必须是奇数,而这里是偶数,舍。故我们要从密串中抠出 \(2\) 位,且这 \(2\) 位对称。

  抠哪里呢?

  这里一般就是盲猜结论了,大佬们都觉很简单……当然我可以写一个推法(?)

  把 \(m=2^{n-1} + 2^{\frac{n}{2}-1}\) 的值写成二进制数,发现只有 \(2\) 位为 \(1\),故该值也写成 \(2^{\frac{n}{2}} - \sum\limits_{k=1}^{n/2} 2^{n-k-1}\)

  \(2^{n-k-1}\) 可以拆成 \(2^{k-1} 2^{n-2k}\)

  观察一下这是什么?设抠掉了密串的第 \(k\) 位和第 \(n-k+1\) 位,\(k-1\) 表示的是密串前 \(k-1\) 位和后 \(k-1\) 位,\(n-2k\) 表示的是密串的第 \(k+1\) 位到第 \(n-k\) 位。那么,第 \(k\) 位和第 \(n-k+1\) 位就被空出来了!可以把这两位当作标记位!

  设 \(x\) 为满足密串第 \(x\) 位不等于第 \(n-x+1\) 位条件下的最小值,我们把所有密串按 \(x\) 从小到大分类。显然 \(x\) 的范围是 \([1,\frac{n}{2}+1]\),其中 \(x=\frac{n}{2}+1\) 的意义比较特殊,表示每一组对称位上的数都相同。

  由于前 \(x-1\) 组对称位上的数都相同,故给每一位放一个 \(0\) 或 \(1\),方案数为 \(2^{x-1}\);第 \(x+1\) 到 \(\frac{n}{2}\) 组对称位上的数没有要求,故给每一位放一个 \(0\) 或 \(1\),方案数为 \(2^{n-2x}\)。

  发现这种设标记位的方式 恰好可以映射 \(m\) 个数。于是我们可以据此构造映射方式了!

  映射方式很简单,我们把密串看成二进制数,自创一个二进制数比大小的规则,以确定 \(m\) 个用于映射的二进制数的排名,其排名 \(-1\) 就是映射到的 \([0,m-1]\) 中的原数。

  规则:以 \(x\) 从小到大为第一关键字,第 \(1\) 到 \(n-x+1\) 组成的二进制数从小到大为第二关键字。

  有了规则,设原数为 \(a\),则加密时求排第 \(a+1\) 名的密串,解密时求密串的排名 \(-1\) 即可。

#include<bits/stdc++.h>
#define ll long long
using namespace std; class Entropy
{
public:
int n;
ll getM(int _n)
{
n = _n;
if(n&1) return 1ll<<(n-1);
else return (1ll<<(n-1))|(1ll<<((n>>1)-1));
}
string getstr(char x) {string ret; ret=ret+(x==0?"0":"1"); return ret;}
string encode(ll x)
{
char str[65];
for(int i=0; i<n-1; i++) str[i] = (x&(1ll<<(n-2-i)))?1:0;
string ret;
if(n&1)
{
for(int i=0; i<((n-1)>>1); i++) ret = ret+getstr(str[i]);
ret = ret+"0";
for(int i=((n-1)>>1); i<n-1; i++) ret = ret+getstr(str[i]);
}
else
{
for(int i=0; i<=(n>>1); i++)
{
ll avail = i<(n>>1)?n-i-2:i,y = (1ll<<avail);
if(x<y)
{
for(int j=0; j<i; j++) {avail--; ret = ret+(x&(1ll<<avail)?"1":"0");}
if(i<(n>>1)) ret = ret+"0";
for(int j=i+1; avail; j++) {avail--; ret = ret+(x&(1ll<<avail)?"1":"0");}
if(i<(n>>1)) ret = ret+"0";
for(int j=i-1; j>=0; j--) {ret = ret+getstr((ret[j]-'0')^1);}
break;
}
x -= y;
}
}
return ret;
}
ll decode(string str)
{
char str0[65]; for(int i=0; i<n-1; i++) str0[i] = str[i]-'0';
ll ret = 0ll;
if(n&1)
{
if(str[n>>1]=='1')
{
for(int i=n-1; i>=0; i--)
{
if(i==(n>>1)) continue;
ret = (ret<<1)|(str[i]=='0'?1ll:0);
}
}
else
{
for(int i=0; i<n; i++)
{
if(i==(n>>1)) continue;
ret = (ret<<1)|(str[i]=='1'?1ll:0);
}
}
}
else
{
for(int i=0; i<=(n>>1); i++)
{
if(i==(n>>1) || str[i]==str[n-1-i])
{
ll tmp = 0ll;
if(str[i]=='0')
{
for(int j=0; j<i; j++) {tmp = (tmp<<1)|(str[j]=='1'?1:0);}
for(int j=i+1; j<n-i-1; j++) {tmp = (tmp<<1)|(str[j]=='1'?1:0);}
}
else
{
for(int j=n-1; j>n-i-1; j--) {tmp = (tmp<<1)|(str[j]=='0'?1:0);}
for(int j=n-i-2; j>i; j--) {tmp = (tmp<<1)|(str[j]=='0'?1:0);}
}
ret += tmp;
break;
}
ret += (1ll<<n-i-2);
}
}
return ret;
}
};
#include "entropy.h"

【安徽集训】Entropy的更多相关文章

  1. 【安徽集训】fiend

    考试的时候只会 \(O(Tn^3)\) 的做法,其它题还都不会,想到一整场就打这么点是人都能写的暴力没啥意思,就懒得写了.. Description 双人博弈.每一轮 A 和 B 同时选择一个 \(1 ...

  2. 【安徽集训】Emerald

    Description \(n\) 座城市在数轴上,第 \(i\) 座城市有一条连向第 \(i+1\) 座城市的单向边.每座城市有一个类型 A/B 以及一个非负整数人口,A 类城市的人觉得自己的城市比 ...

  3. [BZOJ2599][Race][IOI2011]点分治

    这是为了真正去学一下点分治..然后看了迪克李的ppt 又是一道写(改)了很久的题..终于ac了 1354799 orzliyicheng 2599 Accepted 31936 kb 23584 ms ...

  4. NOI2017 酱油记

    侥幸混进市队让我晚退役了几个月..不过终究还是退役了呢..这应该是最后一篇游记了吧.. 考前半个月都在安徽集训..然后发现所有人都停课集训..只有我暑假了开始.. 反正上课各种听不懂..各种被大佬虐. ...

  5. QDEZ集训笔记【更新中】

    这是一个绝妙的比喻,如果青岛二中的台阶上每级站一只平度一中的猫,差不多站满了吧 自己的理解 [2016-12-31] [主席树] http://www.cnblogs.com/candy99/p/61 ...

  6. 一个python的计算熵(entropy)的函数

    计算熵的函数: # -*- coding: utf-8 -*- import math #the function to calculate entropy, you should use the p ...

  7. Shannon entropy

    Shannon entropy is one of the most important metrics in information theory. Entropy measures the unc ...

  8. [转载] Calculating Entropy

    From:  johndcook.com/blog For a set of positive probabilities pi summing to 1, their entropy is defi ...

  9. paper 38 :entropy

    图像熵计算 真是为了一个简单的基础概念弄的心力交瘁,请教了一下师姐,但是并没有真的理解,师弟我太笨呀~~所以,我又查熵的中文含义和相关的出处!共勉吧~~ 1.信息熵: 利用信息论中信息熵概念,求出任意 ...

随机推荐

  1. 鸟哥私房菜基础篇:磁碟配额(Quota)与进阶文件系统管理习题

    猫宁!!! 参考:http://cn.linux.vbird.org/linux_basic/0420quota.php 1-在前一章的第一个大量新增帐号范例中, 如果我想要让每个用户均具有 soft ...

  2. DNS域名解析系统_2

    部署DNS正向解析 主配置文件(/etc/named.conf): 用来定义bind服务程序的运行. 区域配置文件(/etc/named.rfc1912.zones): 用来保存域名和ip地址对应关系 ...

  3. rest_framework 学习笔记(一)

    rest_framework [TOC] 简介 Django REST框架是一个功能强大且灵活的工具包,用于构建Web API. 官方网站:https://www.django-rest-framew ...

  4. ESXi 制作模板并优化 Centos

    1.修改网络配置 vi /etc/sysconfig/network-scripts/ifcfg-eth0 #编辑network配置文件修改以下两项 (eth1同理) ONBOOT=yes BOOTP ...

  5. PTA(Advanced Level)1025.PAT Ranking

    To evaluate the performance of our first year CS majored students, we consider their grades of three ...

  6. mysql函数使用报错

    This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its de 错误解决办法 解决办法也有两种,第一种是在创建 ...

  7. 小程序api使用报错

    小程序连接api报错: 如若已在管理后台更新域名配置,请刷新项目配置后重新编译项目,操作路径:“项目-域名信息” 解决办法如下: 点击设置—-项目设置—勾选如下选项即可解决

  8. python中property属性的介绍及其应用

    Python的property属性的功能是:property属性内部进行一系列的逻辑计算,最终将计算结果返回. 使用property修饰的实例方法被调用时,可以把它当做实例属性一样 property的 ...

  9. Linxu-mysql5.7源码安装

    Mysql5.7 Linux安装教程 1系统约定安装文件下载目录:/data/softwareMysql目录安装位置:/usr/local/mysql数据库保存位置:/data/mysql日志保存位置 ...

  10. 【IntelliJ IDEA】从资源文件读取出来就中文乱码的解决方法

    在application.properties资源文件中设置两个自定义的属性以及属性值: com.sxd.name = "德玛西亚" com.sxd.want = "王者 ...