列表

详情


NC230372. 和生蚝一起做乘法吧

描述

众所周知,生活在蓝星的生蚝是一种好学的生物。
在WUT,就有这么一位生蚝,竞赛绩点项目样样精通,博学多才。
这天,生蚝又在研究一些奇怪的东西。
起因是这样的,有一个学妹来找生蚝,向他请教一个问题:给定一个p,对于的所有数,进行若干次“位交换”操作,最终使得所有数的乘积不为0且乘积最小,问这个最小乘积是什么。
生蚝轻松解答了这个问题,但是博学的生蚝岂能止步于此?于是生蚝又跑来向zech提出了这个问题的加强版本。
zech不会做,于是把这个问题出成题来问你们。

给定区间,这些数经过若干次“位交换”操作后,最终所有数的最小非零乘积是多少。

“位交换”操作:
选择两个数x,y,再选择二进制下某一位k,将xy的二进制第k位进行交换。

输入描述

第一行一个正整数,表示数据组数;
第二行到第行,每行两个正整数,表示区间

输出描述

T行,每行一个正整数表示所求的最小非零乘积,由于答案可能很大,只需要输出答案的值。

示例1

输入:

1
1 7

输出:

1512

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 890ms, 内存消耗: 5028K, 提交时间: 2021-11-24 20:37:25

#include<bits/stdc++.h>
using namespace std;

#define int long long
const int mod = 1e9+7;
int pow2[61];
int cal(int pos,int x) //[0,x]ÔÚµÚposλÉÏÓм¸¸ö1 
{
	int zhouqi = pow2[pos];
	return (x+1)/zhouqi*pow2[pos-1] + max(0LL,(x+1)%zhouqi - pow2[pos-1]);
}
struct node{
	int cnt,id;
}b[61];
bool cmp(node a,node b){
	return a.cnt>b.cnt;
}
int qpow(int a,int k){
	a%=mod;
	int ans=1;
	while(k)
	{
		if(k&1) ans = ans*a%mod;
		a=a*a%mod;
		k>>=1;
	}
	return ans;
}
signed main()
{
	int t;scanf("%lld",&t);
	pow2[0]=1;for(int i=1;i<=60;i++) pow2[i]=pow2[i-1]*2;
	while(t--)
	{
		int l,r;
		scanf("%lld %lld",&l,&r);
		for(int i=1;i<=60;i++) b[i].cnt = cal(i,r)-cal(i,l-1),b[i].id=i;
//		for(int i=1;i<=60;i++)
//		{
//			printf("cnt[%lld]=%lld\n",i,cnt[i]);
//		}
		int mx_cnt = 0;
		for(int i=2;i<=60;i++) mx_cnt = max(mx_cnt,b[i].cnt);
		int n = r-l+1;
		b[1].cnt -= n-mx_cnt;
		
		sort(b+1,b+1+60,cmp);
		int now = 0,ans=1;
		for(int i=1;i<=60;i++)
		{
			if(b[i].cnt==0) continue;
			now += pow2[b[i].id-1];
			ans = (ans * qpow(now,(b[i].cnt-b[i+1].cnt)) ) %mod;
		}
		printf("%lld\n",ans);
	}
}

上一题