gmoj 6844. 【2020.11.02提高組模擬】旅途和生活
阿新 • • 發佈:2020-11-04
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; }