1. 程式人生 > >[HDU-6304] Chiaki Sequence Revisited

[HDU-6304] Chiaki Sequence Revisited

an={1n=1,2anan1+an1an2n3

i=1naimod1000000007

There are multiple test cases. The first line of input contains an integer T(1T105), indicating the number of test cases. For each test case:
The first line contains an integer n(1n1018).

思路

an 序列中某個值 x 出現的次數是 max{k+1|2kx}

然後二分得到 an

然後可以 logan 時間內求出

aianai=2kan[(k+1)gcd(2k,ai)=2kaianai]

然後 減掉多加的部分就得到了答案

ans=aianaii>n,aianai
#pragma GCC optimize ("O2")
#include<bits/stdc++.h>
using namespace std; const int MAXN = (int)1e5 + 5; const int INF = 0x3f3f3f3f; const double EPS = 1e-8; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; const int MOD = 1000000007; ll d[64]; ll f(ll n) { ll num = 0; for(ll i = 1; d[i] <= n; ++i) { num += i * ((n / d[i] + 1
) / 2); } return num + 1; } int sum(ll n) { ll res = 0; for(ll i = 1; d[i] <= n; ++i) { //易錯 (res += i * ((d[i] % MOD + d[i] % MOD + (2 * d[i]) % MOD * (((n / d[i] + 1) / 2 - 1) % MOD) % MOD) % MOD * ((n / d[i] + 1) / 2 % MOD) % MOD * 500000004 % MOD) % MOD) %= MOD; } return (int)res; } ll work(ll n) { // 一定要加速收斂 ll low = max(n / 2, 0LL), top = n / 2 + 30; while(top - low > 1) { ll mid = (low + top) >> 1; if(f(mid) >= n) top = mid; else low = mid; } return top; } void slove(ll n) { ll sop = work(n); ll pos = f(sop); int ans = sum(sop) + 1; ans -= (pos - n) * sop % MOD; printf("%d\n", (ans + MOD) % MOD); } ll read(ll &x) { char c; while((c = getchar()) <= 32); for(x = 0; c >= '0'; c = getchar()) x = x * 10 + c - '0'; } int main() { d[1] = 1; for(int i = 2; i < 64; ++i) d[i] = d[i - 1] << 1; int T;ll n; while(scanf("%d", &T) != EOF) { while(T--) { read(n); slove(n); } } return 0; }