gmoj 6844. 【2020.11.02提高组模拟】旅途和生活

6844. 【2020.11.02提高组模拟】旅途和生活

题目大意

给定a,b,n,求\(lowbit\big(a^n-b^n\big)\)

Solution

证明参考WYD的文章:https://blog.csdn.net/wangyuda123456789/article/details/109458232

对于一奇一偶的情况,\(a^n-b^n\equiv1(mod\ 2)\)恒成立

所以\(lowbit\big(a^n-b^n\big)=1\)

对于两个都是奇数的情况,只能暴力去算,但是

即答案一定在64位之内,所以直接unsigned long long自然溢出就好了

对于两个都是偶数的情况

我们可以通过不断除2使a,b转化成一奇一偶的情况或两个奇数的情况

设除了x次,除剩的数为a',b'

则答案为\(lowbit(a-b)\cdot 2^{x\cdot n}\)

#include <cstdio>
#include <algorithm>
#define MO 1000000007
#define ll unsigned long long
#define LL long long
#define open(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
using namespace std;
int t,n,a,b,x;
ll sum;
LL ans,tmp;
ll ksm(ll x,int y)
{
    ll sum=1;
    while (y)
    {
        if (y&1) sum=sum*x;
        x=x*x;
        y>>=1;
    }
    return sum;
}
LL ks(LL x,int y)
{
    LL sum=1;
    while (y)
    {
        if (y&1) sum=sum*x%MO;
        x=x*x%MO;
        y>>=1;
    }
    return sum;
}
LL mo(int a,int b)
{
	ll sum=ksm(a,n)-ksm(b,n);
	return (sum&(sum^(sum-1)))%MO;
}
int main()
{
    open("journey");
    scanf("%d",&t);
    for (;t;t--)
    {
        scanf("%d%d%d",&a,&b,&n);
        x=0;
        if (((a%2)&&(b%2==0))||((a%2==0)&&(b%2)))
        {
            printf("1\n");
            continue;
        }
        if ((a%2)&&(b%2))
        {
            printf("%lld\n",mo(a,b));
            continue;
        }
        while ((a%2==0) && (b%2==0))
        {
            a/=2;b/=2;x++;
        }
        tmp=ks(2,n*x);
        if (a%2==0 || b%2==0)
        {
            printf("%lld\n",tmp);
        }else 
        {
            ans=mo(a,b)*tmp%MO;
            printf("%lld\n",ans);
        }
    }
    return 0;
}

posted @ 2020-11-04 22:15  Sport_River  阅读(85)  评论(0编辑  收藏  举报