Loading

题面

我们现在要攻击一个程序。

认为两个数相乘花费的时间为两个数二进制下位数的乘积。

\(x\) 的二进制下位数即 \(\lfloor \log_2 x \rfloor + 1\),特别地 \(0\) 的位数 为 \(1\)​​。


给定 \(n,mod\),这个程序有五个内置的参数 \(u, v, k, r, q\),运行框架大致如下:

  • 输入一个 \(n \times n\) 的矩阵 \(A\)
  • \(A_{u,v}\) 设为 \(k \times \left( \sum\limits_{i=0}^{n-1} \sum\limits_{j=0}^{n-1} A_{i,j} \right) + r\)
  • 用矩阵快速幂的方法求出 \(A^q\)具体实现可以参考样例 grader.cpp

所有矩阵的运算均在模 \(mod\) 意义下进行。

每次攻击我们可以输入 \(A\),并得到运行程序所花费的时间(即所有乘法运算时间和)。

我们需要在一定次数内的攻击操作中得知 \(u, v, q\)

由于我们的算力丰富,拥有充分的容错空间,你可以给出不超过 \(500\) 个可能的 \(q\)​​,只要其中有一个是正确的你就会被认为是正确的。


只要你在 \(\color{red}{\le 5\times 10^4}\) 次询问内找出 \(u,v\) 和可能正确的 \(500\)\(q\)可获得该测试点满分

  • 你可以获取 \(u\),调用时会扣除该测试点原始分数的 \(10\%\)

  • 你可以获取 \(v\),调用时会扣除该测试点原始分数的 \(10\%\)

  • 你可以获取 \(k\),调用时会扣除该测试点原始分数的 \(20\%\)

  • 你可以获取 \(r\),调用时会扣除该测试点原始分数的 \(20\%\)

  • 你可以获取 \(q\),调用时会扣除该测试点原始分数的 \(80\%\)

单个测试点分数和 \(0\)\(\max\)

// grader.cpp
namespace grd
{
    int cost;
    inline int len(int x){return x?__lg(x)+1:1;}
    inline LL mul(int x,int y){cost+=len(x)*len(y);return 1ll*x*y;}
    inline Matrix merge(const Matrix &x,const Matrix y)
    {
        Matrix z;memset(z.a,0,sizeof(z.a));
        for(int i=0,j,k;i<n;++i)for(j=0;j<n;++j)for(k=0;k<n;++k)
            z.a[i][k]=(mul(x.a[i][j],y.a[j][k])+z.a[i][k])%mod;
        return z;
    }
    inline int gc(Matrix A,int u,int v,int k,int r,int q)
    {
        cost=0;int s=0;
        for(int i=0,j;i<n;++i)for(j=0;j<n;++j) s=(1ll*s+A.a[i][j])%mod;
        A.a[u][v]=(mul(s,k)+r)%mod;Matrix B;
        for(int i=0,j;i<n;++i)for(j=0;j<n;++j) B.a[i][j]=i==j;
        for(int i=0;i<31;++i)
        {
            if(q>>i&1)B=merge(B,A);
            A=merge(A,A);
        }
        return cost;
    }
}using grd::gc;
// 花费形如 gc 计算

对于 \(100\%\) 的数据,保证 \(mod\) 是素数,\(0\le u,v<n,1\le k,r,q<mod\)

测试点编号 \(n=\) \(mod\) 的范围
\(1\) \(1\) \(2^7 < mod < 2^8\)
\(2\sim 5\) \(2\) \(2^{15} < mod < 2^{16}\)
\(6\sim10\) \(2\) \(2^{30} < mod < 2^{31}\)
posted @ 2025-07-04 12:28  HaHeHyt  阅读(36)  评论(0)    收藏  举报