Codeforces Round #737 (Div. 2) C. Moamen and XOR(数位DP)

Moamen and Ezzat are playing a game. They create an array 𝑎a of 𝑛n non-negative integers where every element is less than 2𝑘2k.

Moamen wins if 𝑎1&𝑎2&𝑎3&…&𝑎𝑛≥𝑎1⊕𝑎2⊕𝑎3⊕…⊕𝑎𝑛a1&a2&a3&…&an≥a1⊕a2⊕a3⊕…⊕an.

Here && denotes the bitwise AND operation, and ⊕⊕ denotes the bitwise XOR operation.

Please calculate the number of winning for Moamen arrays 𝑎a.

As the result may be very large, print the value modulo 10000000071000000007 (109+7109+7).

Input

The first line contains a single integer 𝑡t (1≤𝑡≤51≤t≤5)— the number of test cases.

Each test case consists of one line containing two integers 𝑛n and 𝑘k (1≤𝑛≤2⋅1051≤n≤2⋅105, 0≤𝑘≤2⋅1050≤k≤2⋅105).

Output

For each test case, print a single value — the number of different arrays that Moamen wins with.

Print the result modulo 10000000071000000007 (109+7109+7).

Example

input

Copy

3
3 1
2 1
4 0

output

Copy

5
2
1

看到数据范围很大,于是借助类似数位dp的思想,考虑按位进行处理。设dp[i,0]表示所有数第i位相与大于所有数第i位相异或的数的个数(假设没有第i + 1到第n位),dp[i,1]表示所有数第i位相与等于所有数第i位相异或的数的个数。则输出的就是(dp[k,0]+dp[k,1])%mod。考虑如何进行转移:因为相与和相异或本质上都只和n的奇偶性有关而不和n的大小有关,因此考虑用排列组合的方法进行计算。

当n为奇数:

  1. dp[i,0]=0。因为所有数第i位相与大于所有数第i位相异或的话只能n个数第i位全取1才有可能(否则相与结果必然为0,而相异或结果为0,必然不可能大于)此时所有数相与和相异或的结果都是1,方案数为0。
  2. dp[i,1]=(Cn0+Cn2+Cn4+...+Cnn1+1)×(dp[i1,0]+dp[i1,1])。因为此时有0,2,4.. n - 1个数为1的话相与和相异或都是0,再加上全为1的那一种,最后乘以dp[i - 1]的情况即可。因为当前位与和异或的相等,那么前一位(i - 1)的结果只能是大于或者等于。以及注意这些组合数的和等于2n1

当n为偶数:

  1. dp[i,0]=2(i1)×n,因为当前位结果大于,剩下所有位无论怎么取都可以。
  2. dp[i,1]=(Cn0+Cn2+Cn4+...+Cnn2)×(dp[i1,0]+dp[i1,1])

分析类似,注意Cn0+Cn2+Cn4+...+Cnn2=2n11

#include <bits/stdc++.h>
#define ll long long
#define pb push_back
#define int long long
#define mod 1000000007
using namespace std;
int n, k;
long long dp[200010][2];//大于 等于
long long fpow(long long a, long long b) {
	long long ans = 1;
	for(; b; b >>= 1) {
		if(b & 1) ans = ans * a % mod;
		a = a * a % mod;
	}
	return ans;
}
signed main() {
	int t;
	cin >> t;
	while(t--) {
		cin >> n >> k;
		for(int i = 0; i <= n + 5; i++) {
			dp[i][0] = dp[i][1] = 0;
		}
		if(k == 0) {
			puts("1");
		} else {
			for(int i = 1; i <= k; i++) {
				if(i == 1) {
					if(n & 1) {
						dp[i][0] = 0;
						dp[i][1] = (fpow(2, n - 1) + 1) % mod;//加的1是1 1 1这样的 也算一样
					} else {
						dp[i][0] = 1;
						dp[i][1] = (fpow(2, n - 1) - 1 + mod) % mod;
					}
					continue;
				}
				if(n & 1) {
					dp[i][0] = 0;
					dp[i][1] = (fpow(2, n - 1) + 1 + mod) % mod * (dp[i - 1][0] + dp[i - 1][1]) % mod;
				} else {
					dp[i][0] = fpow(2, (i - 1) * n) % mod;
					dp[i][1] = (fpow(2, n - 1) - 1) % mod * (dp[i - 1][0] + dp[i - 1][1]) % mod;
				}
			}
			cout << (dp[k][0] + dp[k][1]) % mod << endl;
		}
	}
	return 0;
}
posted @   脂环  阅读(66)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2020-08-13 2020杭电多校第八场—Fluctuation Limit
2020-08-13 2020杭电多校第八场—Clockwise or Counterclockwise(几何)
点击右上角即可分享
微信分享提示
主题色彩