Codeforces 题目传送门 & 洛谷题目传送门

u1s1 感觉此题思维难度不太大,不过大概是细节多得到了精神污染的地步所以才放到 D1E 的罢(((

首先我们对所有 \(a_i,b_i\) 分解质因数并将它们全部质因子拎出来编个号 \(1,2,3,\cdots,m\)——这样的质因子个数肯定不会超过 \(2n\omega(a_i)\)。我们记 \(ap_{i,j}\) 表示 \(a_i\) 中标号为 \(j\) 的质因子出现的次数,\(bp_{i,j}\) 表示 \(b_i\) 中标号为 \(j\) 的质因子出现的次数,那么本题等价于找出两个序列 \(k_1,k_2,\cdots,k_n\) 和 \(X_{1},X_2,\cdots,X_m\)使得对于任意质因子 \(j\) 都有 \(ap_{1,j}+k_1bp_{1,j}=ap_{2,j}+k_2bp_{2,j}=\cdots=ap_{n,j}+k_nbp_{n,j}=X_j\),\(k_i\) 表示最终的答案 \(=a_ib_i^{k_i}\),\(X_i\) 表示在最终答案的质因数分解式中编号为 \(i\) 的质因子的出现次数。

考虑对质因子分开来考虑,对于某个质因子 \(j\),如果 \(\exists i\) 使得 \(bp_{i,j}=0\),那么意味着 \(X_j\) 只能等于 \(ap_{i,j}\),此时我们检查是否 \(\exists l\ne i\) 满足 \(bp_{l,j}>0\),如果不存在我们只需检验是否所有 \(ap_{l,j}\) 都等于 \(ap_{i,j}\),如果是那么答案乘上 \(p_j^{X_j}\) 并忽略这个方程,否则我们可以得到一个一元一次方程 \(ap_{l,j}+k_lbp_{l,j}=ap_{i,j}\),如果 \(ap_{i,j}<ap_{l,j}\) 或 \(ap_{i,j}-ap_{l,j}\) 不是 \(bp_{l,j}\) 的倍数那就无解,否则解出 \(k_l\) 之后就可以解出所有 \(X_j\),解出 \(X_j\) 之后再带回去求出其他的 \(k_i\),解完之后再代回去看看是否合法,如果不合法则 \(-1\),合法就直接输出 \(\prod p_j^{X_j}\) 然后退出即可。

处理完 \(\exists bp_{i,j}=0\) 的质因子之后我们默认其余的 \(bp_{i,j}\) 都不等于 \(0\),我们不妨假设 \(1\) 号质因子满足 \(\forall i,bp_{i,1}\ne 0\),那么显然有 \(\forall i,ap_{1,1}+k_1bp_{1,1}=ap_{i,1}+k_ibp_{i,1}\),我们将 \(k_1,k_i\) 当作两个变量,其余当作常数,可得方程 \(k_1bp_{1,1}-k_ibp_{i,1}=ap_{i,1}-ap_{1,1}\),我们考虑另外枚举一个满足 \(\forall i,bp_{i,j}\ne 0\) 的质因子 \(j\),那么也可得类似的方程 \(k_1bp_{1,j}-k_ibp_{i,j}=ap_{i,j}-ap_{1,j}\),如果该方程满足 \(\dfrac{bp_{1,1}}{bp_{1,j}}=\dfrac{bp_{i,1}}{bp_{i,j}}=\dfrac{ap_{i,1}-ap_{1,1}}{ap_{i,j}-ap_{1,j}}\) 则该方程与第一个方程是等价的可以忽略,否则我们就暴力解出 \(k_1,k_i\) 并带回去求出所有的 \(X_i\),再求出别的 \(k_i\) 即可。否则我们根据 \(ap_{1,1}+k_1bp_{1,1}=ap_{2,1}+k_2bp_{2,1}=\cdots=ap_{n,1}+k_nbp_{n,1}=X_1\) 可以得到 \(n\) 个形如 \(X_1\equiv ap_{i,1}\pmod{bp_{i,1}}\) 的同余方程组,exCRT 合并即可,最后可以得到形如 \(X_1\equiv A\pmod{B}\) 的式子,记 \(mx=\max\limits_{i=1}^nap_{i,1}\),当然有可能这里 \(A<mx\),那么就会存在 \(k_i\) 是负数的情况,这是不合法的,因此我们需令 \(A\) 不断加上 \(B\) 直到 \(A\ge mx\),最后我们希望找到的最小的 \(X_1\) 就是 \(A\),解出 \(X_1\) 后就可以求出 \(k_i\),也就可以求出别的 \(X_j\) 了。

u1s1 这题真是精神污染,写了我 3h……

const int MAXN=100;
const int MAXP=1200;
const int MOD=1e9+7;
void exgcd(ll a,ll b,ll &x,ll &y){
if(!b){x=1;y=0;return;} exgcd(b,a%b,y,x);y-=(a/b)*x;
}
int qpow(int x,ll e){
int ret=1;
for(;e;e>>=1,x=1ll*x*x%MOD) if(e&1) ret=1ll*ret*x%MOD;
return ret;
}
int n,m,a[MAXN+5],b[MAXN+5],p[MAXP+5];
bool vis[MAXN+5];
void getpri(int x){
for(int i=2;i*i<=x;i++) if(x%i==0){
p[++m]=i;while(x%i==0) x/=i;
} if(x>1) p[++m]=x;
}
int ap[MAXN+5][MAXP+5],bp[MAXN+5][MAXP+5],ans=1;
ll ans1[MAXP+5],ans2[MAXN+5];
void calc(int x){
int tmpa=a[x],tmpb=b[x];
for(int i=1;i<=m;i++){
while(tmpa%p[i]==0) tmpa/=p[i],ap[x][i]++;
while(tmpb%p[i]==0) tmpb/=p[i],bp[x][i]++;
}
}
void solve(int a1,int b1,int c1,int a2,int b2,int c2){
// debug(20060729);
// printf("%dx+%dy=%d\n%dx+%dy=%d\n",a1,b1,c1,a2,b2,c2);
int lcm=a1/__gcd(a1,a2)*a2;
int mul1=lcm/a1,mul2=lcm/a2;
b1*=mul1;c1*=mul1;b2*=mul2;c2*=mul2;
if((c1-c2)%(b1-b2)) puts("-1"),exit(0);
int x,y;y=(c1-c2)/(b1-b2);
b1/=mul1;c1/=mul1;b2/=mul2;c2/=mul2;
int rem=c1-b1*y;if(rem%a1) puts("-1"),exit(0);
x=rem/a1;if(x<0||y<0) puts("-1"),exit(0);
// printf("%d %d\n",x,y);
for(int i=1;i<=m;i++) ans1[i]=ap[1][i]+x*bp[1][i];
// for(int i=1;i<=m;i++) printf("%d^%lld\n",p[i],ans1[i]);
memset(ans2,-1,sizeof(ans2));
for(int j=1;j<=n;j++){
for(int k=1;k<=m;k++){
if(vis[k]) continue;
if(!bp[j][k]){
if(ap[j][k]!=ans1[k]) return puts("-1"),void();
} else {
if(ap[j][k]>ans1[k]||(ans1[k]-ap[j][k])%bp[j][k]) return puts("-1"),void();
else if(~ans2[j]&&(ans1[k]-ap[j][k])/bp[j][k]!=ans2[j]) return puts("-1"),void();
else ans2[j]=(ans1[k]-ap[j][k])/bp[j][k];
}
}
}
for(int j=1;j<=m;j++) if(!vis[j])
ans=1ll*ans*qpow(p[j],ans1[j])%MOD;
printf("%d\n",ans);
}
bool combine(ll &a1,ll &m1,ll a2,ll m2){
// printf("%lld %lld %lld %lld\n",a1,m1,a2,m2);
ll k1,k2,g=__gcd(m1,m2);exgcd(m1,m2,k1,k2);
if((a2-a1)%g) return 0;ll t=((a2-a1)/g*k1%m2+m2)%m2;
return a1+=t*m1%(m1/g*m2),m1*=m2/g,a1=(a1%m1+m1)%m1,1;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]);
for(int i=1;i<=n;i++) getpri(a[i]),getpri(b[i]);
sort(p+1,p+m+1);m=unique(p+1,p+m+1)-p-1;
for(int i=1;i<=n;i++) calc(i);
for(int i=1;i<=m;i++){
int pos0=0,pos1=0;
for(int j=1;j<=n;j++){
if(!bp[j][i]) pos0=j;
else pos1=j;
}
if(pos0){
// printf("%d\n",i);
if(!pos1){
for(int j=1;j<=n;j++) if(ap[j][i]!=ap[1][i])
return puts("-1"),0;
ans=1ll*ans*qpow(p[i],ap[1][i])%MOD;vis[i]=1;
} else {
if(ap[pos0][i]<ap[pos1][i]) return puts("-1"),0;
if((ap[pos0][i]-ap[pos1][i])%bp[pos1][i]) return puts("-1"),0;
int cc=(ap[pos0][i]-ap[pos1][i])/bp[pos1][i];
// printf("%d %d %d\n",pos0,pos1,cc);
for(int j=1;j<=m;j++) ans1[j]=1ll*bp[pos1][j]*cc+ap[pos1][j];
memset(ans2,-1,sizeof(ans2));
for(int j=1;j<=n;j++){
for(int k=1;k<=m;k++){
if(vis[k]) continue;
if(!bp[j][k]){
if(ap[j][k]!=ans1[k]) return puts("-1"),0;
} else {
if(ap[j][k]>ans1[k]||(ans1[k]-ap[j][k])%bp[j][k]) return puts("-1"),0;
else if(~ans2[j]&&(ans1[k]-ap[j][k])/bp[j][k]!=ans2[j]) return puts("-1"),0;
else ans2[j]=(ans1[k]-ap[j][k])/bp[j][k];
}
}
}
for(int j=1;j<=m;j++) if(!vis[j])
ans=1ll*ans*qpow(p[j],ans1[j])%MOD;
printf("%d\n",ans);return 0;
}
}
} int pos=1;while(vis[pos]) pos++;
if(pos==m+1) return printf("%d\n",ans),0;
for(int i=1;i<=n;i++) swap(ap[i][pos],ap[i][1]),swap(bp[i][pos],bp[i][1]);
swap(vis[pos],vis[1]);swap(p[pos],p[1]);debug(1);
// printf("%d\n",pos);
for(int j=2;j<=m;j++) if(!vis[j]){
for(int i=2;i<=n;i++){
if(bp[1][1]*bp[i][j]!=bp[1][j]*bp[i][1]){
solve(bp[1][1],-bp[i][1],ap[i][1]-ap[1][1],
bp[1][j],-bp[i][j],ap[i][j]-ap[1][j]);
return 0;
}
}
} //debug(20060617);
ll A=ap[1][1]%bp[1][1],M=bp[1][1],mx=ap[1][1];
// debug(114514);
for(int i=2;i<=n;i++){
if(!combine(A,M,ap[i][1]%bp[i][1],bp[i][1]))
return puts("-1"),0;
chkmax(mx,ap[i][1]);
} //debug(20210406);
if(A<mx) A+=(mx-A+M-1)/M*M;
ll cc=(A-ap[1][1])/bp[1][1];
for(int i=1;i<=m;i++) ans1[i]=ap[1][i]+cc*bp[1][i];
// for(int i=1;i<=m;i++) printf("%d^%lld\n",p[i],ans1[i]);
memset(ans2,-1,sizeof(ans2));
for(int j=1;j<=n;j++){
for(int k=1;k<=m;k++){
if(vis[k]) continue;
if(!bp[j][k]){
if(ap[j][k]!=ans1[k]) return puts("-1"),0;
} else {
if(ap[j][k]>ans1[k]||(ans1[k]-ap[j][k])%bp[j][k]) return puts("-1"),0;
else if(~ans2[j]&&(ans1[k]-ap[j][k])/bp[j][k]!=ans2[j]) return puts("-1"),0;
else ans2[j]=(ans1[k]-ap[j][k])/bp[j][k];
}
}
}
for(int j=1;j<=m;j++) if(!vis[j])
ans=1ll*ans*qpow(p[j],ans1[j])%MOD;
printf("%d\n",ans);
return 0;
}

Codeforces 571E - Geometric Progressions(数论+阿巴细节题)的更多相关文章

  1. CodeForces 567C Geometric Progression

    Geometric Progression Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I ...

  2. CodeForces 567C. Geometric Progression(map 数学啊)

    题目链接:http://codeforces.com/problemset/problem/567/C C. Geometric Progression time limit per test 1 s ...

  3. [CodeForces - 1225C]p-binary 【数论】【二进制】

    [CodeForces - 1225C]p-binary [数论][二进制] 标签: 题解 codeforces题解 数论 题目描述 Time limit 2000 ms Memory limit 5 ...

  4. Codeforces Round #392 (Div. 2)-758D. Ability To Convert(贪心,细节题)

    D. Ability To Convert time limit per test 1 second Cmemory limit per test 256 megabytes input standa ...

  5. Codeforces 633C Spy Syndrome 2 | Trie树裸题

    Codeforces 633C Spy Syndrome 2 | Trie树裸题 一个由许多空格隔开的单词组成的字符串,进行了以下操作:把所有字符变成小写,把每个单词颠倒过来,然后去掉单词间的空格.已 ...

  6. 【线段树 细节题】bzoj1067: [SCOI2007]降雨量

    主要还是细节分析:线段树作为工具 Description 我们常常会说这样的话:“X年是自Y年以来降雨量最多的”.它的含义是X年的降雨量不超过Y年,且对于任意Y<Z<X,Z年的降雨量严格小 ...

  7. Codeforces Round #524 (Div. 2)(前三题题解)

    这场比赛手速场+数学场,像我这样读题都读不大懂的蒟蒻表示呵呵呵. 第四题搞了半天,大概想出来了,但来不及(中途家里网炸了)查错,于是我交了两次丢了100分.幸亏这次没有掉rating. 比赛传送门:h ...

  8. codeforces 257div2 B. Jzzhu and Sequences(细节决定一切)

    题目链接:http://codeforces.com/contest/450/problem/B 解题报告:f1 = x,f2 = y,另外有当(i >= 2) fi = fi+1 + fi-1 ...

  9. Codeforces 1045B Space Isaac - 数论 - Hash

    题目传送门 传送门I 传送门II 传送门III 题目大意 给定将$\left \{ 0, 1, \dots, m - 1\right \}$分成了不相交的两个非空集合$A$和$B$,给定$A$,问存在 ...

随机推荐

  1. .Net Core微信服务商二次进件

    最近商城进行微信服务商二次进件的开发,大致有几个点 一,服务商签名 二,服务商证书获取 三,图片上传 四,敏感信息加密 五,查询进件状态 除此之外,就是进件信息的拼装 电商二级商户进件申请单-状态流转 ...

  2. Python绘制Excel图表

    今天讲解下如何使用Python绘制各种Excel图表,下面我们以绘制饼状图.柱状图.水平图.气泡图.2D面积图.3D面积图为例来说明. import openpyxlfrom openpyxl imp ...

  3. LeetCode:树专题

    树专题 参考了力扣加加对与树专题的讲解,刷了些 leetcode 题,在此做一些记录,不然没几天就没印象了 力扣加加-树专题 总结 树的定义 // Definition for a binary tr ...

  4. Noip模拟47 2021.8.25

    期望得分:55+24+53 实际得分:0+0+3 乐死 累加变量清零了吗? 打出更高的部分分暴力删了吗? 样例解释换行你看见了吗? T1 Prime 打出55分做法没删原来的暴力,结果就轻松挂55分 ...

  5. c语言编程基础入门必备知识

    数据类型 基本数据类型 类型名称说明char字符类型存放字符的ASCII码int整型存放有符号整数short短整型存放有符号整数long长整型存放有符号整数long long存放有符号整数float单 ...

  6. Python环境配置详细步骤以及第一个程序

    打开python官网:https://www.python.org/ 在官网找与自己电脑系统匹配的版本路径  这里以python3.7.2版本为例: 下载完成后,使用管理员身份进行安装:  打开命令提 ...

  7. stm32学习笔记之GPIO功能框图分析

    GPIO 是通用输入输出端口的简称,简单来说就是STM32 可控制的引脚,STM32 芯片的GPIO 引脚与外部设备连接起来,从而实现与外部通讯.控制以及数据采集的功能.STM32 芯片的GPIO被分 ...

  8. VCS常用仿真选项开关及步骤总结

    转自:https://blog.csdn.net/bcs_01/article/details/79803304 转自:https://blog.csdn.net/wonder_coole/artic ...

  9. cf12E Start of the season(构造,,,)

    题意: 给一个偶数N. 构造出一个矩阵. 满足:主对角线上全为0.每一行是0~N-1的一个全排列.矩阵关于主对角线对称. 思路: 觉得是智商题,,,,看完题解后觉得不难,但是我就是没想出来.只想到了前 ...

  10. 第07课 OpenGL 光照和键盘(1)

    光照和键盘控制: 在这一课里,我们将添加光照和键盘控制,它让程序看起来更美观. 这一课我会教您如何使用三种不同的纹理滤波方式.教您如何使用键盘来移动场景中的对象,还会教您在OpenGL场景中应用简单的 ...