B 赛博算命 (模拟)

B 赛博算命


Description:

  • 假设第一轮比赛共有 $ k \geq 2 $名选手,有以下规定:
  • 如果存在整数 \(n\) 使得 \(k =2^n\),那么编号为 \(1\) 的选手对战编号为 \(2^n\) 的选手,那么编号为 \(2\) 的选手对战编号为 \(2^n-1\) 的选手,以此类推,没有选手轮空,这一场比赛结束后,只剩下 \(2^{n-1}\) 个选手。
  • 如果存在整数 \(n\) 使得 \(2^{n-1} < k < 2^n\),在保证第一轮结束后还剩下 \(2^{n-1}\) 个选手的前提下,编号为 \(1\) 的选手对战编号为 \(k\) 的选手,编号为 \(2\) 的选手对战编号为 \(k-1\) 的选手,以此类推,剩下一些编号中间的选手轮空,如果轮空,则认为对手的编号为 \(k+1\) 号。
  • 已知自己和队友们的编号,求对手的编号的乘积(结果对\(10^9+7\)取模)

Constraints:

  • \(1 \leq q \leq 10^6, 2 \leq k \leq 10^9, q\leq k\)

Analysis:

  • 模拟题

Solution:

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

#define mod 1000000007

typedef long long ll;
typedef unsigned long long ull;

const int maxn = 1e5+5;
const int maxm = 1e6+5;

ll qpow(ll a,ll n) {
	ll ans = 1;
	while(n) {
		if(n & 1) ans *= a;
		a *= a;
		n >>= 1; 
	}
	return ans;
}
map<int,ll> mp; //记录幂指数
vector<int> v;
int main() {
	for(int i=0;i<31;i++) mp[i] = qpow(2,i); //初始化
	
	int n,k; cin >> n >> k;
	for(int i=0;i<n;i++) {
		int id; cin >> id;
		v.push_back(id);
	}
	ll ans = 1;
	for(int i=0;i<31;i++) {
		if(k == mp[i]) {
			for(int j=0;j<v.size();j++) {
				ans = ans * (k-v[j]+1) % mod;
			}
			break;
		}
		if(mp[i] < k && k < mp[i+1]) {
			for(int j=0;j<v.size();j++) {
				if(v[j] >= mp[i]+1 || v[j] <= k-mp[i]) ans = ans * (k+1-v[j]) % mod;
				else ans = ans * (k+1) % mod;
			}
			break;
		}
	}
	cout << ans << endl;
	return 0;
}
posted @ 2023-11-11 19:19  Trilliverse  阅读(15)  评论(0编辑  收藏  举报