洛谷 P4317

题目链接: P4317 花神的数论题

题目大意

详见题目

solution

\(f_{i, j, k}\) 表示长度为 \(i\) 最高位为 \(j\) 的且 \(1\) 的个数为 \(k\) 的数的个数

  1. \(j=1, \ f_{i, j, k} = \sum\limits_{p = 0}^{p \leqslant 1}\sum\limits_{k = 0}^{k \leqslant i} f_{i - 1, p, k - 1}\)
  2. \(j=0, \ f_{i, j, k} = \sum\limits_{p = 0}^{p \leqslant 1}\sum\limits_{k = 0}^{k \leqslant i} f_{i - 1, p, k}\)

对于\(ans_{1, r}\) 我们可以采用以下策略 :

\(len\)\(r\) 的位数, \(a_{len}\)\(r\) 的每一位

  1. 对于首位为 \(1\) 且前面有 \(cnt1\)\(1\)\(f\) , \(res = res * j^{f_{i, 0, j}}, i \in [1, len), j \in [1, len / 2 - cnt1]\)
  2. 对于首位为 \(0\)\(f\) , \(res = res * j^{f_{i, 1, j}}, i \in [1, len), j \in [1, i / 2]\)

那么答案就是 \(ans_{1, r}\)

Code:

/**
*    Author: Aliemo
*    Data: 
*    Problem: 
*    Time: O()
*/
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>

#define int long long
#define rr register

#define inf 1e9
#define MAXN 100010

using namespace std;

const int mod = 10000007;

inline int read() {
	int s = 0, f = 0;
	char ch = getchar();
	while (!isdigit(ch)) f |= ch == '-', ch = getchar();
	while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
	return f ? -s : s;
}

void print(int x) {
	if (x < 0) putchar('-'), x = -x;
	if (x > 9) print(x / 10);
	putchar(x % 10 + 48);
}

int l, r, len;

int f[80][2][80], a[50];

inline int f_pow(int x, int y) {
	int ans = 1;
	while (y)  {
		if (y & 1) ans = ans * x % mod;
		x = x * x % mod;
		y >>= 1;
	}
	return ans % mod;
}

inline void init() {
	f[1][1][1] = 1, f[1][0][0] = 1;
	for (rr int i = 2; i < 64; i++) 
		for (rr int j  = 0; j <= 1; j++) 
			for (rr int k = 0; k <= i; k++)
				for (rr int p = 0; p <= 1; p++) 
					if (!j) f[i][j][k] += f[i - 1][p][k];
					else if (k) f[i][j][k] += f[i - 1][p][k - 1];
}

inline int solve(int x) {
	memset(a, 0, sizeof a);
	len = 0;
	int ans = 0, cnt1 = 1;
	while (x) {
		a[++len] = x % 2;
		ans += a[len];
		x /= 2;
	}
	for (rr int i = len - 1; i >= 1; i--) {
		int x = a[i];
		if (x) {
			for (rr int j = 0; j <= len - cnt1; j++)
				if (f[i][0][j] != 0)
					ans = (f_pow(j + cnt1, f[i][0][j]) * ans) % mod;
		}
		cnt1 += x;
	}
	for (rr int i = 1; i < len; i++)
		for (rr int j = 1; j <= i; j++)
			if (f[i][1][j] != 0) 
				ans = (f_pow(j,f[i][1][j]) * ans) % mod;
	return ans % mod;
}

signed main() {
	init();
	r = read();
	cout << solve(r);
}
posted @ 2020-11-17 09:08  Aliemo  阅读(52)  评论(0编辑  收藏  举报