https://acm.hdu.edu.cn/showproblem.php?pid=6983
杭电多校的一道题,深刻觉得自己太菜了。
开始打表,然后找结构变化,写了一大篇,乱的不行。
标程是记忆化搜索,醉了,话说也好久没用过了。
乱写ac代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i, x, y) for(auto i=(x);i<=(y);++i)
#define dep(i, x, y) for(auto i=(x);i>=(y);--i)
#define gcd(a, b) __gcd(a,b)
const long long mod = 1e9 + 7;
const int maxn = 100000 + 5;
int lowbit(int x) { return x & -x; }
bool ispow(int n) { return (n & (n - 1)) == 0; }//O(1) 判断是否是 2^k(2的k次方)
int read() {
int x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int n, k;
int sum=0;
void build(long long l, long long r) {
sum++;
if (r - l + 1 <= k) return ;
long long mid = (l + r) / 2;
build(l, mid);
build(mid + 1, r);
return ;
}
int build1(int l,int r,int z,int cnt) {
if (r - l + 1 <= k) return cnt;
long long mid = (l + r) / 2;
cnt=build1(1,mid,z<<1,cnt+1);
return cnt;
}
int f(int x){
int pp= build1(1, x, 1, 0);
if(ispow(pp)||ispow(pp-1))
return 2*pp-1;
return ((long long)1<< build1(1, x, 1, 0))+f(x/2);
}
signed main() {
//freopen("1.in","r",stdin);
int t ;
cin>>t;
while(t--){
cin >> n >> k;
sum = 0;
// build(1, n);
//cout << sum << endl;
int cnt=0;
int ans=0;
int ps=0;
int N=n;
if (n % k > 0)n = n / k + 1;
else n = n / k;
// if(!ispow(n))
for(int i=1;i<=60;i++){
if(n>((long long)1<<(i-1))&&n<=((long long)1<<(i)))
{
cnt=i-1;
ps = n - ((long long) 1 << cnt);
break;
}
}
N-=((int)1<<cnt)*k;
N*=2;
if(N>(int)1<<(cnt+1))N=( (int) 1 << (cnt + 1));
int flag=0;
ans=N;
n=((int)1<<cnt);
ans+=n;
while(n!=1){
flag=n%2;
ans+=n/2;
n=n/2+flag;
}
cout<<ans<<endl;
}
return 0;
}
记忆化搜索:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
#define rep(i, x, y) for(auto i=(x);i<=(y);++i)
#define dep(i, x, y) for(auto i=(x);i>=(y);--i)
#define gcd(a, b) __gcd(a,b)
const long long mod = 1e9 + 7;
const int maxn = 100000 + 5;
int lowbit(int x) { return x & -x; }
bool ispow(int n) { return (n & (n - 1)) == 0; }//O(1) 判断是否是 2^k(2的k次方)
int read() {
int x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int Case;
ll n, k;
map<int ,int >mp;
ll dfs(ll n) {
int res=0;
if(mp[n])return mp[n];
if(k>=n)
return 1;
mp[n]=dfs(n/2)+dfs((n+1)/2)+1;
res+=mp[n];
return res;
}
signed main() {
scanf("%d", &Case);
while (Case--) {
scanf("%lld%lld", &n, &k);
mp.clear();
printf("%lld\n", dfs(n));
}
}
7万+

被折叠的 条评论
为什么被折叠?



