一场极其失败的cf,并不是出题少而是整个人不在状态,思路想的不满但是很多细节全部忽略或者脑瘫,例如b爆ll这个点早就想到了但就是没有反应过来无论是右边界设置为k还是k / 2都会爆ll,要不是最后造数据察觉到不对劲甚至这题都不一定能ac.这道b,20min思路正确敲完代码,但在这脑瘫错误上wa了4发还从22min就该ac一直拖到写完c的99min,分数完全没了.
这道a题实际上就是考察对二进制的理解并加以拓展,只要想到把n化成k进制后每一位上的数xi就是n由xi * k^i组成之后处理特判就行
#define yyy cout<<"Yes"<<"\n"
#define nnn cout<<"No"<<"\n"
#define x first
#define y second
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll , ll> pii;
const int N = 2e5 + 10,inf = 0x3f3f3f3f;
void work()
{
ll n,k;
cin>>n>>k;
if(k == 1 || k > n)
{
cout<<n<<"\n";
}else
{
int ans = 0;
while(n)
{
ll x = n % k;
if(x)
{
ans += x;
}
n /= k;
}
cout<<ans<<"\n";
}
}
int main()
{
IOS;
int t;
cin>>t;
while(t--)
{
work();
}
}
接下来是本场败笔的b,我们只需要关心i这个灯是不是被操作了偶数次即可,也就是说他是不是有偶数个因子,知道了这个本质我们就可以快速的手玩出一组数据可以发现亮灯是以公差为2首项为2的等差数列,每一组亮灯之间隔着一个灭灯,那么我们只需要找到小于等于k的mid * (mid + 1),那么若mid * (mid + 1) < k,那么答案就是mid * (mid + 1) + mid + k - mid * (mid + 1) + 1 = k + mid + 1,若k == mid * (mid + 1)那么答案就是k + mid,因为此时不需要算上间隔的那个灭灯,这个mid可以二分出来,我的败笔就在于想到了k是1e18很大,直接有边界为k的话中间的mid * (mid + 1)绝对会爆ll,然后我就自鸣得意的将r设置成了k / 2??????????????????????????????????,我都不知道自己怎么想的k / 2 * (k / 2 + 1)难道就不爆了???????????????????正确的边界是sqrt(k),这样正好可以在范围内。。。。。。。。。。。。。。。。。。。。。。。。
#define yyy cout<<"Yes"<<"\n"
#define nnn cout<<"No"<<"\n"
#define x first
#define y second
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll , ll> pii;
const int N = 2e5 + 10,inf = 0x3f3f3f3f;
void work()
{
ll k;
cin>>k;
ll l = 0,r = sqrt(k);
while(l < r)
{
ll mid = (l + r + 1) / 2;
ll x = mid * (mid + 1);
if(x > k)
{
r = mid - 1;
}else
{
l = mid;
}
}
// cout<<r<<" ";
// cout<<r * (r + 1)<<" "<<(r + 1) * (r + 2)<<"\n";
// cout<<r<<"\n";
if(r * (r + 1) == k)
{
cout<<k + r<<"\n";
}else if(r * (r + 1) < k)
{
cout<<k + r + 1<<"\n";
}
}
int main()
{
IOS;
int t;
cin>>t;
while(t--)
{
work();
}
}
直接列出真值表即可,要想到二进制的加法中1 + 1 = 0,1 - 1 = 0,1 + 0 = 1,难点在于会出现一些位置既可以是0也可以是1,但是若全部是0那么有可能不能构成等式,若全是1那么会超过2^61,那么这时我们可以为了防止爆炸先全部选择0,并且记录所有选择0抛弃1的位置,之后我们一一比对,若ans + qmi(2 , i) <= qmi(2 , 61)的话那么就加上不然就不加,这题wa了两次一个是没有注意到这个贪心的思路一个是图省事用的pow,但是pow时doube的范围会爆炸..........................
#define yyy cout<<"Yes"<<"\n"
#define nnn cout<<"No"<<"\n"
#define x first
#define y second
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll , ll> pii;
const int N = 2e5 + 10,inf = 0x3f3f3f3f;
void get(ll x,vector <ll> &y)
{
while(x)
{
y.push_back(x % 2);
x /= 2;
}
return;
}
ll qmi(ll a,ll b)
{
ll res = 1;
while(b)
{
if(b & 1)
{
res = res * a;
}
a = a * a;
b /= 2;
}
return res;
}
void work()
{
ll b,c,d;
cin>>b>>c>>d;
vector <ll> bb,cc,dd,aa;
get(b , bb);
get(c , cc);
get(d , dd);
ll ans = 0;
vector <ll> id;
for(ll i = 0 ; i < max((ll)bb.size() , max((ll)cc.size() , (ll)dd.size())) ; i++)
{
ll x,y,z;
if(i < bb.size())
{
x = bb[i];
}else
{
x = 0;
}
if(i < cc.size())
{
y = cc[i];
}else
{
y = 0;
}
if(i < dd.size())
{
z = dd[i];
}else
{
z = 0;
}
if((!x && !y && !z) || (x && y && z) || (!x && !y && z))
{
if(!x && !y && z)
{
id.push_back(i);
}
continue;
}else if((!x && y && z) || (x && !y && !z))
{
cout<<-1<<"\n";
return;
}else
{
ans += qmi(2 , i);
}
}
ll num = qmi(2 , 61);
for(int i = 0 ; i < id.size() ; i++)
{
if(ans + qmi(2 , id[i]) <= num)
{
ans += qmi(2 , id[i]);
}
}
cout<<ans<<"\n";
}
int main()
{
IOS;
int t;
cin>>t;
while(t--)
{
work();
}
}