B 清楚姐姐学构造【2023牛客寒假算法基础集训营4】
B 清楚姐姐学构造
题意
给出三个同余式子,分类讨论
思路
\[\left\{
\begin{array}{}
a_i \equiv a_{N-1-i}\ (mod\ m) & \\
b_i \equiv -b_{N-1-i}\ (mod\ m) &\\
c_i \equiv a_i + b_i\ (mod\ m) &
\end{array}
\right.
\]
\[整理得
\]
\[\left\{
\begin{array}{}
c_i + c_{n-i-1} \equiv 2a_i\ (mod\ m) & \\
c_i - c_{n-i-1} \equiv 2b_i\ (mod\ m) &
\end{array}
\right.
\]
\[a_i = ((c_i + c_{n-i-1}) \cdot inv(2)) mod\ m
\]
\[b_i = ((c_i - c_{n-i-1}) \cdot inv(2)) mod\ m\
\]
代码
点击查看代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
#define X first
#define Y second
typedef pair<int,int> pii;
typedef long long LL;
const char nl = '\n';
const int N = 1e6+10;
const int M = 1e6+10;
int n,m;
LL c[N],b[N],a[N];
int qmi(int a,int k,int p){ //快速幂求逆元
LL res = 1;
while(k){
if(k&1)res = (LL)res%p*a%p; //注意要变为LL否则会爆int!!!
a = (LL)a%p*a%p;
k >>= 1;
}
return res;
}
void solve(){
bool f = 0;
cin >> n >> m;
for(int i = 0; i < n; i ++)cin >> c[i];
if(m == 2){ //如果m=2则不能求2的逆元,m整除a则不存在逆元
for(int i = 0; i < n/2; i ++)
if(c[i]%2!=c[n-i-1]%2) //相加减必须为偶数不然不满足同余
f = 1;
if(f)cout << "no" << nl;
else{
cout << "yes" << nl;
for(int i = 0; i < n; i ++)cout << c[i] << " ";
cout << nl;
for(int i = 0; i < n; i ++)cout << 0 << " ";
cout << nl;
}
}
else{
int inv = qmi(2,m-2,m); //或者(m+1)/2
for(int i = 0; i < n/2; i ++){
a[i] = (LL)(c[i]+c[n-i-1])*inv%m;
a[n-i-1] = a[i];
b[i] = (LL)(c[i]-c[n-i-1]+m)%m*inv%m;
b[n-i-1] = (m-b[i])%m;
}
if(n%2){ //奇数要特判构造中间的一个数
b[n/2] = 0;
a[n/2] = c[n/2];
}
cout << "yes" << nl;
for(int i = 0; i < n; i ++)cout << a[i] << " ";
cout << nl;
for(int i = 0; i < n; i ++)cout << b[i] << " ";
cout << nl;
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
solve();
}
结论
- 2的逆元比较特殊,(m+1)/2【因为m是质数则m必定为奇数,(m+1)/2必定为正整数】

浙公网安备 33010602011771号