题意:你可以进行二种操作:
操作一:
可以将x变成F(x),F(x)=(x * x * x+x * x)%233;
操作二:
可以将x变成G(x),G(x)=(x * x * x-x * x)%233;
求最少多少次可以使a变成b,如果无解则输出-1;
思路:
先对233以内的数到233以内的数进行预处理:
d[i][j]表示i变成j的最少操作次数。
初始化dp[i][j]=一个极大值
dp[i][i]=0;
如果i可以通过一次操作变成j,则dp[i][j]=1;
使用Floyd算法求出i到j的最少操作次数。
预处理后,我们分以下三种情况判断:
①:a==b,输出0;
②:b>=233,输出-1;
③:a先操作一次,然后用预处理的结果求出值。
代码:
#include <bits/stdc++.h> #include <iostream> #include <cstdio> #include <algorithm> #include <string> #include <cstring> #include <vector> using namespace std; typedef long long ll; int d[250][250], inf=233; int main() { fill(d[0],d[0]+250*250,1000000007); for(int i=0; i<233; i++) { d[i][i]=0; for(int j=0; j<233; j++) { if(i==j) { continue; } if((i*i*i+i*i)%233==j) { d[i][j]=1; } if((i*i*i-i*i)%233==j) { d[i][j]=1; } } } for(int k=0; k<233; k++) { for(int i=0; i<233; i++) { for(int j=0; j<233; j++) { d[i][j]=min(d[i][j],d[i][k]+d[k][j]); } } } int t; scanf("%d",&t); while(t--) { ll a, b; scanf("%lld%lld",&a,&b); if(a==b) { printf("0\n"); } else if(b>=233) { printf("-1\n"); } else { ll z=0; int k=(a%inf*a%inf*a%inf+a%inf*a%inf)%inf; z=1+d[k][b]; k=(a%inf*a%inf*a%inf-a%inf*a%inf+inf)%inf; z=min(z,(ll)1+d[k][b]); if(z>=1000000007) { z=-1; } printf("%lld\n",z); } } return 0; }