E
题意:
对于区间[l r]之中的数。我们选出两个数字来,分别进行乘三的操作,和除三(向下取整),至少需要多少次操作,使得全部的数变成零。
我们可以将log 的数值,预处理出来。同时注意到t=1e4, r=2e5.
如果每次累加起来就会超时。所以我们处理log的前缀和。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+10;
int log_3[N];
void init()
{
log_3[1]=0;log_3[0]=0;
log_3[3]=1;
for (int i=3;i<=N;i++)
log_3[i]=log_3[i/3]+1;
//处理前缀和
for (int i=1;i<=N;i++)
{
log_3[i]+=log_3[i-1];
}
}
void solve()
{
int l,r;cin>>l>>r;
int ans=0;
ans+=2*(log_3[l]-log_3[l-1]+1);
ans+=log_3[r]-log_3[l]+(r-l);
cout<<ans<<"\n";
}
F
题意:
二进制的数组。取出数组长度为k(k为奇数)的所有子序列。求出他们的中位数(排序之后,在中间位置的数字,因为中位数还要排序,其实就没有了子序列中的相对顺序的限制,可以随便选了)的和,输出和mod1e9+7
中位数不是0就是1,所以一个子序列的贡献不是0,就是1.也就是说中位数是1的时候,才有贡献,否则没有影响。
因为只有01,所以只要这个子序列中的0的个数小于等于 k/2,中位数就是1.那么这几个子序列就会贡献1.
现在的问题就是 这样的子序列的有多少个。
可以统计数组中0 和1 的个数。
枚举0的个数,利用组合数求解。
多mod总是没错的^ _ ^
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1e9+7;
const int N=2e5+10;
int f[N],g[N];
int qpow(int a,int b)
{
int ans=1;a%=mod;
while(b){
if (b&1)ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
void init()
{
f[0]=g[0]=1;
for (int i=1;i<N;i++)
{
f[i]=f[i-1]*i%mod;
//逆元
g[i]=g[i-1]*qpow(i,mod-2)%mod;
}
}
int getc(int n,int m){
if (m>n)return 0;
return f[n]*g[m]%mod*g[n-m]%mod;
}
void solve()
{
int n,k;cin>>n>>k;
vector<int>a(n);int cnt[2]{};
for (int i=0;i<n;i++)
cin>>a[i],cnt[a[i]]++;
int tar=k/2;int ans=0;
for (int i=0;i<=tar;i++)
{
ans+=(getc(cnt[0],i)*getc(cnt[1],k-i)%mod)%mod;
}
cout<<ans%mod<<"\n";
}
G
题意:
交互题,有一个数x(2~999)
如果y<x 返回的是 y
否则是 y+1
3^7=2187 >999.所以可以在7次询问之前,找到答案。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int ask(int x,int y)
{
cout<<"? "<<x<<" "<<y<<endl;
int ans;cin>>ans;
return ans;
}
void solve()
{
int l=2,r=999;
while(l<=r)
{
int midl=l+(r-l)/3;
int midr=r-(r-l)/3;
int now=ask(midl,midr);
if (now==midl*midr)
{
l=midr+1;
}else if (now==midl*(midr+1))
l=midl+1,r=midr-1;
else r=midl-1;
}
cout<<"! "<<l<<endl;
}
int main()
{
std::cin.tie(nullptr)->sync_with_stdio(false);
int t; cin>>t;
while(t--)
{
solve();
}
return 0;
}