「CF1060H」Sophisticated Device 题解
题目简介
题目简介超出了笔者的表述能力范围,所以挂上codeforces和洛谷的直达链接。
分析
感谢洛谷题解区破壁人五号和T_E_I_O_大佬的博客提供思路和参考。
0x0.
一些前置定义:
tot:已用的格子总数。
mod:即原题目中的\(p\)。
z:数字 \(0\) 的所在位置,默认为 \(5000\),可以看做 \(p\) 个 \(1\) 相加再\(\mod p\),实现参考某速乘:
inline int init(int a,int b,int p=0){
if(!p)p=++tot;
while(b){
if(b&1)print_plus(a,p,p);
b>>=1;
print_plus(a,a,a);
}
return p;
}
z=init(4999,mod-1,5000);
print_plus():输出加法:
inline int print_plus(int a,int b,int c){std::cout<<"+ "<<a<<' '<<b<<' '<<c<<'\n';return c;}
print_power():输出幂运算:
inline int print_power(int a,int b){std::cout<<"^ "<<a<<' '<<b<<'\n';return b;}
clear():将某个格子赋值为 \(0\)。
inline int clear(int p=0){if(!p)p=++tot;return print_plus(z,z,p);}
copy():将一个格子的值赋给另一个格子:
inline int copy(int x,int p=0){if(!p)p=++tot;return print_plus(z,x,p);}
0x1.
当 \(d=2\) 时,很容易想到,\(xy=\frac{(x+y)^2-x^2-y^2}{2}\) (初中知识)。
其中有减法和除法,考虑如何实现。
一致看向取模
0x2.
先讲乘法
\[x\times y=\sum_{i=1}^{x}y
\]
可以考虑某速乘的方法:
inline int multi(int a,int b,int p=0){
p=clear(p);
int x=copy(a);
return init(x,b%mod,p);
}
0x3.
对于减法,考虑\(a-b\equiv a+(p-1)b\ (mod\ p)\)
inline int minu(int a,int b){return print_plus(a,multi(b,mod-1),++tot);}
0x4
对于除法,即乘以其逆元。
题目保证 \(p\),也就是本题解中的 \(mod\) 为一个质数,所以可以用费马小定理求其逆元:
inline ll quickly_power(ll a,int b){
ll ans=1;
while(b){
if(b&1)ans=(ans*a)%mod;
b>>=1;
a=(a*a)%mod;
}
return ans;
}
0x5
这是本题中最重要,最难理解的一步。
令
\[x^2=\sum_{i=0}^{d}[a_i\times(x+i)^d]=a_0\times(x+0)^d+a_1\times(x+1)^d+\dots+a_d\times(x+d)^d
\]
耐心地将其展开,可以得到:
\[x^2=\sum_{i=0}^{d}[C_{d}^{i}\sum_{j=0}^d(a_i\times j^i)\times x^{d-i}]
\]
\[x^2=C_{d}^{0}(a_0+a_1+\dots+a_d)\times x^d+C_{d}^{1}(a_0\times 0^1+a_1\times 1^1+\dots+a_d\times d^1)\times x^{d-1}\dots C_{d}^{d}(a_0\times 0^d+a_1\times 1^d+\dots+a_d\times d^d)\times x^0
\]
要使这个式子成立,只需满足:
\[C_{d}^{0}(a_0+a_1+\dots+a_d)\times x^d=0
\]
\[C_{d}^{1}(a_0\times 0^1+a_1\times 1^1+\dots+a_d\times d^1)\times x^d=0
\]
\[\dots
\]
\[C_{d}^{d-2}(a_0\times 0^{d-2}+a_1\times 1^{d-2}+\dots+a_d\times d^{d-2})\times x^2=1
\]
\[\dots
\]
\[C_{d}^{d}(a_0\times 0^d+a_1\times 1^d+\dots+a_d\times d^d)\times x^0=0
\]
已知前面那项 \(C\neq 0\),\(x^k\) 未知。
所以:
\[a_0+a_1+\dots+a_d=0
\]
\[a_0\times 0^1+a_1\times 1^1+\dots+a_d\times d^1=0
\]
\[\dots
\]
\[C_{d}^{d-2}(a_0\times 0^{d-2}+a_1\times 1^{d-2}+\dots+a_d\times d^{d-2})=1
\]
\[\dots
\]
\[a_0\times 0^d+a_1\times 1^d+\dots+a_d\times d^d=0
\]
高斯消元即可
\(AC\ Code\)
#include<cstdio>
#include<iostream>
#include<functional>
typedef long long ll;
int tot=3,z;
ll mod;
inline int print_plus(int a,int b,int c){std::cout<<"+ "<<a<<' '<<b<<' '<<c<<'\n';return c;}
inline int print_power(int a,int b){std::cout<<"^ "<<a<<' '<<b<<'\n';return b;}
inline int clear(int p=0){if(!p)p=++tot;return print_plus(z,z,p);}
inline int copy(int x,int p=0){if(!p)p=++tot;return print_plus(z,x,p);}
inline ll quickly_power(ll a,int b){
ll ans=1;
while(b){
if(b&1)ans=(ans*a)%mod;
b>>=1;
a=(a*a)%mod;
}
return ans;
}
inline int init(int a,int b,int p=0){
if(!p)p=++tot;
while(b){
if(b&1)print_plus(a,p,p);
b>>=1;
print_plus(a,a,a);
}
return p;
}
inline int multi(int a,int b,int p=0){
p=clear(p);
int x=copy(a);
return init(x,b%mod,p);
}
inline int minu(int a,int b){return print_plus(a,multi(b,mod-1),++tot);}
ll a[12][12];
ll c[12];
void Gauss(int d){
for(int i=0;i<=d;++i)
for(int j=0;j<=d;++j){
a[i][j]=quickly_power(j,i);
if(i==d-2)a[i][j]=(a[i][j]*d*(d-1)>>1)%mod;
}
a[d-2][d+1]=1;
for(int i=0;i<=d;++i){
for(int j=i;j<=d;++j)
if(a[j][i]){std::swap(a[i],a[j]);break;}
ll tmp=quickly_power(a[i][i],mod-2);
for(int j=0;j<=d;++j){
if(i==j)continue;
long double b=a[j][i]*tmp%mod;
for(int k=0;k<=d+1;++k){
a[j][k]-=a[i][k]*b;
a[j][k]=(a[j][k]%mod+mod)%mod;
}
}
}
for(int i=0;i<=d;++i)c[i]=a[i][d+1]*quickly_power(a[i][i],mod-2)%mod;
}
inline int power(int p,int d){
int x=copy(p),y=clear(),ans=clear();
for(int i=0;i<=d;++i){
print_plus(x,y,++tot);
print_power(tot,tot+1);++tot;
int tmp=multi(tot,c[i]);
print_plus(tmp,ans,ans);
print_plus(4998,y,y);
}
return ans;
}
int main(){
int d;std::cin>>d>>mod;
print_plus(1,2,3);
z=init(4999,mod-1,5000);
Gauss(d);
int x=power(1,d),y=power(2,d);
int z=power(3,d);
printf("f %d\n",multi(minu(minu(z,x),y),quickly_power(2,mod-2)));
return 0;
}

浙公网安备 33010602011771号