1. 程式人生 > 實用技巧 >gmoj 6844. 【2020.11.02提高組模擬】旅途和生活

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;
}