本人 6年级 耗时2个月luoguP1737 [NOI2016] 旷野大计算AC
接下来由我为大家讲解
输出的是 𝑎a 的二进制表示,肯定只包含 00 和 11 。
可以想到,这题又要用 𝑆(𝑥)S(x) 函数来搞出 00 和 11 。
用 𝑆(𝑥)S(x) 获得 00 和 11 要求自变量 𝑥x 有正负两种取值,所以我们构造这个正负的取值。
考虑 𝑎a 的 22 进制的最高位,即第 3131 位,很显然,若这一位为 11 ,则 𝑎⩾231a⩾231 ;若这一位为 00 ,则 𝑎<231a<231 ,于是我们减去 231231 就能搞出正负不同的取值了。
同样的,我们需要加上 10−1010−10 来保证 𝑆(𝑥)S(x) 不会恰好取到 1221 。
由此我们发现,𝑆(𝑥)S(x) 函数能够用来比较变量和某个常数之间的大小关系。
我们至少需要将减去 231231 后的数左移 4141 位以爆掉精度。这是 task4task4 中计算过的。
所以我们计算最高位时就输出 𝑆((𝑎−231)×241)S((a−231)×241) ,即 𝑆(𝑎×241−272)S(a×241−272) 。
我们得到 00 或 11 后,把它左移恰当位数后再从原数中减去,得到 𝑎′a′ ,就可以继续对下一位搞出正负两种取值了。第二高位答案就是 𝑆((𝑎′−230)×241)=𝑆(𝑎′×241−271)S((a′−230)×241)=S(a′×241−271) 。
诶?还是乘 4141 哎!
于是我们发觉,可以一开始就将 𝑎a 左移 4141 位,以减少计算节点数。
但这样搞就需要我们计算出 242242 到 272272 这 3131 个幂次方了。计算这些幂次方可以用高精(三个 𝑙𝑜𝑛𝑔 𝑙𝑜𝑛𝑔long long 拼起来就足够了),可以用 pow
函数,也可以用计算器来手动模拟压位高精。
当然最靠谱的方法就是用题目提供的 checker
来计算。写好计算节点,输入 11 ,让 checker
自己跑出来 242242 到 272272 。省时省力。
接下来送出AC代码 代码为C++98 运行
感谢大家的收看
#include <bits/stdc++.h>
using namespace std;
int tot;
int In(){
printf("I\n");
return ++tot;
}
int Out(int x){
printf("O %d\n", x);
return ++tot;
}
int add(int x, int y){
printf("+ %d %d\n", x, y);
return ++tot;
}
int addc(int x, int c){
printf("C %d %d\n", x, c);
return ++tot;
}
int addc(int x, double c){
printf("C %d %.10lf\n", x, c);
return ++tot;
}
int addc(int x, char* c){
printf("C %d %s\n", x, c);
return ++tot;
}
int addc(int x, string c){
printf("C %d %s\n", x, c.c_str());
return ++tot;
}
int neg(int x){
printf("- %d\n", x);
return ++tot;
}
int lsh(int x, int c){
printf("< %d %d\n", x, c);
return ++tot;
}
int rsh(int x, int c){
printf("> %d %d\n", x, c);
return ++tot;
}
int sig(int x){
printf("S %d\n", x);
return ++tot;
}
int sgn(int x){
int a = lsh(x, 500);
a = sig(a);
a = lsh(a, 1);
a = addc(a, -1);
return a;
}
int p(int x){
return sig(lsh(x, 500));
}
int Abs(int x){
int b = lsh(p(addc(x, "0.00000000000000000000001")), 152);
int c = rsh(x, 150);
int d = sig(add(c, b));
d = addc(d, -0.5); d = neg(d);
d = lsh(d, 153); d = add(d, b);
return add(x, d);
}
int min0(int x){
int b = lsh(p(addc(x, "0.00000000000000000000001")), 151);
int c = rsh(x, 150);
int d = sig(add(c, b));
d = addc(d, -0.5); b = neg(b);
d = lsh(d, 152); d = add(d, b);
return d;
}
int max0(int x, int y, int c){
x = neg(x);
int b = lsh(p(x), 151);
int d = sig(add(c, b));
d = addc(d, -0.5); b = neg(b);
d = lsh(d, 152); d = add(d, b);
return d;
}
int a[50],b[50];
int turn10(int *a){
int ret = add(a[0], lsh(a[1], 1));
for(int i = 2; i <= 31; i ++){
ret = add(ret, lsh(a[i], i));
}
return ret;
}
void turn2(int x, int *a){
x = lsh(x, 500);
for(int i = 31; i >= 1; i --){
int tmp = addc(x, (-pow(2, i) + 0.01) * pow(2, 500));
tmp = sig(tmp);
a[i] = tmp;
tmp = neg(lsh(tmp, 500 + i));
x = add(x, tmp);
}
a[0] = rsh(x, 500);
}
int xor1(int x, int y){
int a = add(x, y);
int b = addc(a, -1.5);
b = neg(p(b));
b = lsh(b, 1);
return add(a, b);
}
void xor32(int *a, int *b){
for(int i = 0; i <= 31; i ++) a[i] = xor1(a[i], b[i]);
}
int div10(int x){
string a = "2.06343706889556054705";
string sa = "-0.887298334620741688550198422716226773933599412474263948504833186119911079463425709202638465";
return lsh(addc(sig(addc(rsh(x, 150), a)), sa), 150);
}
int modadd(int x, int y, int cc, int rshc, int negc){
int s = add(x, y);
int tmp = add(s, cc);
return add(s, max0(tmp, negc, rshc));
}
int main(){
int n;
cin>>n;
if(n==1 || n==7){
int a = In(), b = In();
a = add(a, b);
a = lsh(a, 1);
a = neg(a);
Out(a);
}
if(n==2){
int a = In();
int b = a;
a = lsh(a, 4);
a = add(a, b);
a = neg(a);
Out(sig(a));
}
if(n==3){
int a = In();
a = lsh(a, 500);
a = sig(a);
a = lsh(a, 1);
a = addc(a, -1);
Out(a);
}
if(n==4){
int a = In();
Out(Abs(a));
}
if(n==5){
for(int i = 31; i >= 0; i --){
a[i] = In();
}
Out(turn10(a));
}
if(n==6){
int x = In();
turn2(x, a);
for(int i = 31; i >= 0; i --) Out(a[i]);
}
if(n==8){
int x = In();
Out(div10(x));
}
if(n==9){
for(int i = 1; i <= 16; i ++){
a[i] = In();
}
for(int i = 1; i < 16; i ++){
for(int j = i + 1; j <= 16; j ++){
int t = add(a[i], a[j]);
a[i] = add(a[i], min0(add(neg(a[i]), a[j])));
a[j] = add(t, neg(a[i]));
}
}
for(int i = 1; i <= 16; i ++){
Out(a[i]);
}
}
if(n==10){
int x = In(); int y = In(); int c = In(); int negc = neg(c); int rshc = rsh(negc, 150); int cc = addc(negc, "0.0000001");
turn2(x, a);
x = rsh(x, 1000);
for(int i = 31; i >= 0; i --){
x = add(x, x);
x = modadd(x, a[i], cc, rshc, negc);
}
turn2(y, b);
int d = x; x = rsh(x, 1000);
for(int i = 31; i >= 0; i --){
x = modadd(x, x, cc, rshc, negc);
x = modadd(x, max0(addc(b[i], "-0.5"), d, rsh(d, 150)), cc, rshc,negc);
}
Out(x);
}
return 0;
}