函数的魔法
函数的魔法
https://ac.nowcoder.com/acm/problem/21884
题意:你可以进行二种操作:
操作一:
可以将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;
}
每日一题题解 文章被收录于专栏
写题解
腾讯云智研发成长空间 254人发布
