QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#811287#241. Chiaki Sequence Revisitedrlc202204100 ✓96ms3828kbC++172.1kb2024-12-12 17:26:002024-12-12 17:26:01

Judging History

你现在查看的是最新测评结果

  • [2024-12-12 17:26:01]
  • 评测
  • 测评结果:100
  • 用时:96ms
  • 内存:3828kb
  • [2024-12-12 17:26:00]
  • 提交

answer

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 105;
const int mod = 1e9 + 7;

void add(int &x, int y) {
	x = (x + y) % mod;
}


int a[N] = {0};

void fnd() {
	int n;
	cin >> n;
	a[1] = 1, a[2] = 1;
	for (int i = 3; i <= n; i++)
		a[i] = a[i - a[i - 1]] + a[i - 1 - a[i - 2]];
	int l = 2, r;
	while (l <= n) {
		r = l;
		int cnt = 0;
		while (r <= n && a[r] == a[l])
			cnt++, r++;
		printf("(%d, %d): %d cnt = %d\n", l - 1, r - 2, a[l], cnt);
		l = r;
	}
} 

int pw[100] = {0};
int pws[100] = {0};
//?? lowbit ?? 
int res[100] = {0};
long long cnt[100] = {0};

int cal(int k) {
	//?? 1 ~ 2^k - 1 ? i log(lowbit(i)) 
	int ans = 0;
	for (int j = 1; j <= k; j++) {
		int sum = 1ll * pws[k - j] * pw[j] % mod;
		add(sum, 1ll * pw[j - 1] * pw[k - j] % mod);
		add(ans, 1ll * j * sum % mod);
		cnt[k] += j * (1ll << (k - j));
	//	if (k == 2)
	//		cout << j << " " << sum << endl;
	}
	return ans;
}

int f(long long n, int k) {
	if (n == 0ll)
		return 0;
//	cout << "At " << n << " " << k << " " << endl;	
	if (k == 1)
		return 1;
	if (n <= cnt[k - 1])
		return f(n, k - 1);
	if (n - cnt[k - 1] <= k)
		return (res[k - 1] + (n - cnt[k - 1]) * pw[k - 1] % mod) % mod;
	int ans = 0;
	add(ans, res[k - 1]);
	add(ans, 1ll * k * pw[k - 1] % mod);
	
//	cout << k << " : " << "ans: " << ans << endl;
		
	n -= cnt[k - 1];
	n -= k;
	add(ans, n % mod * pw[k - 1] % mod);
	add(ans, f(n, k - 1));
	
	return ans;
}

void slv() {
	long long n;
	cin >> n;
	n--;
	cout << (f(n, 60) + 1) % mod << endl;
}

int main() {
//	fnd();
	pw[0] = 1;
	for (int i = 1; i <= 60; i++)
		pw[i] = 2ll * pw[i - 1] % mod;
	for (int i = 1; i <= 60; i++) 
		pws[i] = 1ll * (pw[i] - 1) * pw[i - 1] % mod;
	for (int i = 0; i <= 60; i++) {
		res[i] = cal(i);
	//	if (i <= 5)
	//		cout << i << " " << cnt[i] << endl;
	/*	if (i < 5) {
			int ans = 0;
			for (int j = 1; j < (1 << i); j++) {
				int k = 0;
				while (!(j >> k & 1))
					k++;
				ans += (k + 1) * j;
			}
//			cout << "Chk " << ans << endl; 
		}*/
	}
//	return 0;
	int T;
	scanf("%d", &T);
	while (T--)
		slv();
	return 0;
}

詳細信息


Pretests


Final Tests

Test #1:

score: 100
Accepted
time: 96ms
memory: 3828kb

input:

100000
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
1...

output:

1
2
4
6
9
13
17
21
26
32
38
45
53
61
69
77
86
96
106
117
129
141
153
166
180
194
209
225
241
257
273
289
306
324
342
361
381
401
421
442
464
486
509
533
557
581
605
630
656
682
709
737
765
793
822
852
882
913
945
977
1009
1041
1073
1105
1138
1172
1206
1241
1277
1313
1349
1386
1424
1462
1501
1541
158...

result:

ok 100000 lines