题解 CF1060H Sophisticated Device【高斯消元】

题目链接

这道题实在是毒瘤。以及洛谷上的翻译其实是我翻的,质量跟机翻差不多。

首先我们确定求出 x y xy xy 的整体思路—— x y = ( x + y ) 2 − x 2 − y 2 xy=(x+y)^2−x^2−y^2 xy=(x+y)2x2y2

这个思路不难想到:我们能够比较容易实现的两个操作数的运算只有加、减,于是我们将运算转换为加、减与只有一个操作数的平方、除以 2。关键在于如何实现这些运算。

前置技能

  • 快速幂/乘
  • 高斯消元
  • exgcd 求乘法逆元
  • 少量数学知识
  • 大量耐心

我们先考虑几个简单的运算:

在求解过程中,有一个数字 0 是很方便的,利用 ·+ zero zero x· 就可以清空一格。

在这里需要用到快(慢?)速乘,实现:

int f=p-1;
while(f){
   
    if(f&1ll){
   
        cout<<"+ "<<4998<<" "<<zero<<" "<<zero<<endl;
    }
    cout<<"+ "<<4998<<" "<<4998<<" "<<4998<<endl;
    f/=2;
}
//zero=4999

这样 zero 格就有了一个常数 0。

乘以常数

同样是快速乘。要注意的是,每次必须清空所需格子。

int getmulti(int a,int b,int q){
   
    b=(b%p+p)%p;
    int ans=(q?q:++tot);
    int x=++tot;
    while(b){
   
        if(b&1ll){
   
            cout<<"+ "<<x<<" "<<ans<<" "<<ans<<endl;
        }
        cout<<"+ "<<x<<" "<<x<<" "<<x<<endl;
        b/=2;
    }
    return ans;
}
//如果有 q ,答案存在 q 当中。返回结果所在格子。

减法

a − b = a + ( p − 1 ) b a−b=a+(p−1)b ab=a+(p1)b

int jian(int a,int b){
   
    b=getmulti(b,p-1);
    ++tot;
    cout<<"+ "<<a<<" "<<b<<" "<<tot<<endl;
    return tot;
}

除以常数

即乘以其逆元。

下面是重头戏:

求一个数的平方

很明显, x 2 x^2 x2 并不能通过 x d x^d xd 直接求出。

我们考虑将 x 2 x^2 x2 表达为 a 0 ( x + 0 ) d + a 1 ( x + 1 ) + ⋯ + a d ( x + d ) d a_0(x+0)^d+a_1(x+1)^+\dots+a_d(x+d)^d a0(x+0)d+a1(x+1)++ad(x+d)d

将它展开,再按 x x x 合并同类项,得:

x 2 = C d 0 ( a 0 + a 1 + ⋯ + a d ) x d + C d 1 (

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值