L - Little Difference Gym - 101612L(二分答案)

 题目链接:http://codeforces.com/gym/101612/attachments

题解:

先考虑到特殊情况:如果该数是n的次幂的话,肯定能分解成任意个1与对应个2的乘积,此时输出-1。

在考虑下题意,该数只能被分解成a^len或a^i*(a+1)*(len-i),由于n达到1e18,与2的60次方接近,即分解式中最多包含60位左右,不妨枚举到64,那么我们可以二分每个分解式的因子个数,即len,二分答案更改标志为a^i<=n,只有这样才能保证n能被只由n分解或者被a和a+1分解。(仔细想一下,这样的思路是对的,因为只要对应分解式中的因子个数固定,该分解方式一定是唯一的或者没有)

#include
using namespace std;
typedef long long ll;
ll n,tot,MAP[100][100];

int ok(ll x,int len)//len个x是否满足小于等于n的条件
{
    ll sum=1;
    for(int i=1;i<=len;i++){
        if(n/sum>=x)sum*=x;
        else return 0;
    }
    return 1;
}
int judge(ll a,int len1,ll b,int len2)//len1个a和len2个b的乘积是否为n
{
    ll sum=1;
    for(int i=1;i<=len1;i++){
        if(n/sum>=a)sum*=a;
        else return 0;
    }
    for(int i=1;i<=len2;i++){
        if(n/sum>=b)sum*=b;
        else return 0;
    }
    if(sum==n)return 1;
    return 0;
}
void add(ll a,int len1,ll b,int len2)//添加答案
{
    ++tot;
    MAP[tot][0]=len1+len2;
    for(int i=1;i<=len1;i++)
        MAP[tot][i]=a;
    for(int i=1;i<=len2;i++)
        MAP[tot][i+len1]=b;
}
int main()
{
    freopen("little.in", "r", stdin);
    freopen("little.out", "w", stdout);
    cin>>n;
    ll m=n;
    while(m%2==0)m/=2;
    if(m==1){            //只要是2的次幂,就可以分解成2和任意个1的乘积,即无穷种分解方法,输出-1
        cout<<"-1"<

 

你可能感兴趣的:(二分)