C-圆
分析
结论:分割的平面个数是 $n^2-n+2$ 。
F-二进制位数变化
分析
看数据范围是要我们预处理,预处理出 $[1,n]$ 增加所对应的二进制位数变化之和,从 $[x,y]$ 用 $f[x+y]$ - $f[x]$ 。用暴力求出一段区间变化,观察各位上变化的性质。得出,第0位每加1变化1次,第1位每加2变化1次,第2位每加4变化1次,所以第 $x$ 位置,每加 $(1<<x)$ 变化1次。 所以就每位去累计变化数即可,
法1(暴力)->用来找规律+检验
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N=1e5+10;
int t;
string f(int x)
{
string str;
while(x)
{
str+=char(x%2+'0');
x/=2;
}
reverse(str.begin(),str.end());
return str;
}
void solve()
{
int x,y;
cin>>x>>y;
int sum=0;
while(y--)
{
int cnt=0;
string a=f(x);
x++;
string b=f(x);
while(a.size()<b.size())a='0'+a;
for(int i=0;i<b.size();i++)
{
if(a[i]!=b[i])cnt++;
}
sum+=cnt;
}
cout<<sum<<endl;
}
signed main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>t;
while(t--)solve();
return 0;
}
法二 (前缀和)
//要计算[x,x+y]的变化,前缀和,f[x+y]-x[x]即可,看时间复杂度肯定是要预处理的,无论从哪里开始加,都是
//[1,x+y]-[1,x]所以预处理从1开始即可,最大数是2e6
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N=2e6+10;
typedef pair<int,int>P;
int t,c[N],f[N];
//暴力会超时
int get(int x)
{
return c[(x&-x)];//返回二进制下最后出现1的位置
}
void init()
{
//f[n]表示[1~n]二进制位数变化和
c[1]=1;
for(int i=1;i<=20;i++)
{
c[1<<i]=1+i;
//c[1]=1 c[2]=2 c[4]=3 c[8]=4 c[16]=5……c[1048576]=21
}
for(int i=1;i<=2e6;i++)
{
f[i]=get(i);
f[i]+=f[i-1];
}
}
void solve()
{
int x,y;
cin>>x>>y;
cout<<f[x+y]-f[x]<<endl;
}
signed main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>t;
init();//记得初始化!!!
while(t--)solve();
return 0;
}
法三 (每位计算)
#include<bits/stdc++.h>
using namespace std;
void solve()
{
int x,y;
cin>>x>>y;
int ans=0;
for(int i=0;i<=20;i++)//枚举从0位开始,第20位对应的10进制数就已经超过了1e6
{
int c=(1<<i);//每一位是1<<该位置来加的
if(c>(x+y))break;//超了就退出
if(y%c==0)
ans+=y/c;
else
{
ans+=y/c;
if(y/c*c+(c-(x%c)-1)<y)ans++;//看多余的能否再加一次
}
}
cout<<ans<<endl;
}
signed main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int t;
cin>>t;
while(t--)solve();
return 0;
}
D-异或为零
分析
暂时不是很懂
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
int n,x,t=-1;
signed main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n;
int ans=0;
for(int i=0;i<n;i++)
{
cin>>x;
if(x!=t)
{
t=x;
if(x!=0)ans++;
}
}
cout<<ans;
return 0;
}
//每次选定[l,r]的数字来与al去异或第i次操作,左端点大于i的操作不会影响到ai,对于ai来说左端点位i-1覆盖不到ai
//当a1=0或者a1=a2时,左端点为1的操作会覆盖到a2,