A.
直接从最小的开始构造即可,最小的差值都不能满足最大的肯定也不能满足
#include
using namespace std;
const int N = 2e5+10,mod=1e9+7;
#define int long long
typedef long long LL;
typedef pair PII;
int n;
int a[N];
void solve(){
int x,y;
cin>>x>>y>>n;
a[1]=x;
a[n]=y;
int now=1;
for(int j=n-1;j>=1;j--)
{
a[j]=a[j+1]-now;
now++;
}
if(a[1]>=x)
{
a[1]=x;
for(int j=1;j<=n;j++) cout<>t;
while(t--) solve();
}
B.
分析性质:
第一个操作,可以让同奇偶的不同位置数任意交换
第二个操作,可以改变当前数的下标的奇偶性(k%2==0,可以改变),否则不能改变
如果可以任意改变直接排序即可否则
所以直接把不同下标的扣出来排序即可
#include
using namespace std;
const int N = 2e5+10,mod=1e9+7;
#define int long long
typedef long long LL;
typedef pair PII;
int n,k;
int a[N];
void solve(){
cin>>n>>k;
string s;
cin>>s;
if(k%2==0){
sort(s.begin(),s.end());
cout< b,c;
for(int i=0;i>t;
while(t--) solve();
}
C.
我们可以逆着操作且等价
我们先尽可能靠近n,每次加上自己,因为1*n=n,n是自己的因子
这个操作其实很像倍增,相当于每次加一个2^i
最后不能加了,我们考虑差值
先想想当前数有哪些因子,因为最终答案肯定是某一个2^i,所以他的因子肯定可以表示2^x*2^y(x,y<=i)
所以我们用二进制凑出这个差值即可
并且每个2^i最多用两次
#include
using namespace std;
const int N = 3010,mod=1e9+7;
#define int long long
typedef long long LL;
typedef pair PII;
int n,k;
int g[N][N];
void solve(){
//线性dp
cin>>n;
int res=0;
int x=1;
vector a;
while(x<=n)
{
a.push_back(x);
if(x*2>n) break;
x*=2;
}
int y=n-a.back();
for(int i=60;i>=0;i--)
{
if(y>>i&1)
{
a.push_back((a.back()+(1ll<>t;
while(t--) solve();
}
D.首先因为操作当前(i,j),只会改变下面行的状态,所以直接从开头行枚举,有1就只能操作
然后用一个懒标记,标记数组变化
维护三个数组,因为改变的是以当前(i,j)为头的金字塔
所以维护一个斜左右下角,垂直向下,
#include
using namespace std;
#define int long long
const int N = 3010, inf = 0x3f3f3f3f3f;
int n;
char s[N][N];
void sovle() {
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)
cin>>s[i][j];
}
int res=0;
vector> l(n+2,vector(n+2,0));
vector> d(n+2,vector(n+2,0));
vector> r(n+2,vector(n+2,0));
vector> val(n+2,vector(n+2,0));
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(l[i][j]){
val[i][j]^=1;
l[i+1][j-1]^=1;
d[i+1][j]^=1;
}
if(d[i][j]){
val[i][j]^=1;
d[i+1][j]^=1;
}
if(r[i][j]){
val[i][j]^=1;
r[i+1][j+1]^=1;
d[i+1][j]^=1;
}
int num=s[i][j]-'0';
if(num^val[i][j])
{
res++;
l[i+1][j-1]^=1;
d[i+1][j]^=1;
r[i+1][j+1]^=1;
}
}
}
cout<> t;
while (t--) {
sovle();
}
}
E:
首先手玩一下
a,b ,c=a|b
第一轮:如果a最高位的1和c最高位不等于 可以判断 a 第二轮:如果a最高位的1和c最高位不等于 || b的次高位不等于c的次高位(因为第一轮可以得出最高位的a一定是1) 可以判断
第三轮:(由前两轮得出最高位得1和次高位的1,b都有)(可以得到b的最高位1跟a的1一样)如果a的次高位不等于c的次高位 || a的第三位1不等于c的第三位1
.....
可以观察得出只能1的个数有关,所以我们直接用01trie,去dfs一遍边算边计算贡献
要记录当前点前面有多少个1
然后计算轮数的时候,如果tr[u][0]&&tr[u][1]当前此高位能分出01
那么贡献是当前数的个数*两个人的轮数(因为当前可能是到第一个人操作也可能是第二个人操作,因为给第一个a的数,给二个人b的数,可以反过来,因为题目选的数随机)
如果最后没有就证明a=b,直接结束即可,那么贡献就是全部1的个数了
#include
using namespace std;
const int N = 2e5+10,mod=998244353;
#define int long long
typedef long long LL;
typedef pair PII;
int n,m;
int tr[N*32][2],tot,len[N*32],cnt[N*32],ans;
int qmi(int a, int k, int p) // 求a^k mod p
{
int res = 1 % p;
while (k)
{
if (k & 1) res = (LL)res * a % p;
a = (LL)a * a % p;
k >>= 1;
}
return res;
}
void dfs(int u){
if(!tr[u][0]&&!tr[u][1]){
ans=(ans+1ll*cnt[u]*cnt[u]%mod*(len[u]+1)%mod)%mod;
return ;
}
if(tr[u][0]&&tr[u][1])//次高位
{
int lef=cnt[tr[u][0]],rig=cnt[tr[u][1]];
int x=len[u]+1,y=len[u]+2;
ans=(ans+1ll*lef*rig%mod*(x+y)%mod)%mod;
}
if(tr[u][0])dfs(tr[u][0]);
if(tr[u][1])dfs(tr[u][1]);
}
void solve(){
tot=0,ans=0;
cin>>n;
for(int i=1,x;i<=n;i++){
cin>>x;
int p=0;
for(int j=30;j>=0;j--){
int c=x>>j&1;
if(!tr[p][c])
tr[p][c]=++tot,len[tot]=len[p]+(c==1);
p=tr[p][c];
cnt[p]++;
}
}
dfs(0);
ans=1ll*ans*qmi(n*n%mod,mod-2,mod)%mod;
cout<>t;
while(t--) solve();
}
F.
首先手玩样例,最少操作次数肯定是区间不同数的个数(cnt数组就是处理这个的,前缀和),根据贪心我们尽可能选择连续的区间操作
2 3 2 6 3 10 1 2
对于l,r=2,3
3 2 6 3这个区间,把6去掉看成
3 2 3,这个2是把无法避免要把两个3分开操作的,否则就变成-1了,
对于相同数的两个位置=x,y
如果[x+1,y-1]中有一个数mx满足 mx>=l&& mx
所以对于这个操作我们需要离线处理,每次固定一个右端点,然后找到当前[x+1,y-1]
区间中,最大的满足
然后考虑计算贡献,先不考虑 l 的位置,如果满足区间中,最大的满足
这个数需要给[1,r],[2,r],[3,r].....[mx,r]这些不同的 l 都需要加上一个代价1,所以我们直接把[1,mx]的区间去增加一个1,最后答案就是不同数的个数加上当前bit【l】的值了,这里用的是树状数组
把区间[1,mx]都加一,用了差分处理的,最后求当前l的值就是他的前缀和,一开始差分数组都是0
所以初始化树状数组不用特别处理
#include
using namespace std;
const int N = 2e6+10,mod=1e9+7;
#define int long long
typedef long long LL;
typedef pair PII;
int n,m;
int a[N];
vector pos[N];
vector query[N];
int ans[N];
template
struct Fenwick{
int n;
vector tr;
Fenwick(int n) : n(n), tr(n + 1, 0){}
int lowbit(int x){
return x & -x;
}
void modify(int x, T c){
for(int i = x; i <= n; i += lowbit(i)) tr[i] += c;
}
void modify(int l, int r, T c){
modify(l, c);
if (r + 1 <= n) modify(r + 1, -c);
}
T query(int x){
T res = T();
for(int i = x; i; i -= lowbit(i)) res += tr[i];
return res;
}
T query(int l, int r){
return query(r) - query(l - 1);
}
int find_first(T sum){
int ans = 0; T val = 0;
for(int i = __lg(n); i >= 0; i--){
if ((ans | (1 << i)) <= n && val + tr[ans | (1 << i)] < sum){
ans |= 1 << i;
val += tr[ans | (1 << i)];
}
}
return ans + 1;
}
int find_last(T sum){
int ans = 0; T val = 0;
for(int i = __lg(n); i >= 0; i--){
if ((ans | (1 << i)) <= n && val + tr[ans | (1 << i)] <= sum){
ans |= 1 << i;
val += tr[ans | (1 << i)];
}
}
return ans;
}
};
using BIT = Fenwick;
struct Info {
int mx = 0;
};
Info operator+(const Info &a, const Info &b){
return {max(a.mx, b.mx)};
}
template
struct SegmentTree{
int n;
vector info;
SegmentTree() {}
SegmentTree(int n, Info _init = Info()){
init(vector(n, _init));
}
SegmentTree(const vector &_init){
init(_init);
}
void init(const vector &_init){
n = (int)_init.size();
info.assign((n << 2) + 1, Info());
function build = [&](int p, int l, int r){
if (l == r){
info[p] = _init[l - 1];
return;
}
int m = (l + r) / 2;
build(2 * p, l, m);
build(2 * p + 1, m + 1, r);
pull(p);
};
build(1, 1, n);
}
void pull(int p){
info[p] = info[2 * p] + info[2 * p + 1];
}
void modify(int p, int l, int r, int x, const Info &v){
if (l == r){
info[p] = v;
return;
}
int m = (l + r) / 2;
if (x <= m){
modify(2 * p, l, m, x, v);
}
else{
modify(2 * p + 1, m + 1, r, x, v);
}
pull(p);
}
void modify(int p, const Info &v){
modify(1, 1, n, p, v);
}
Info query(int p, int l, int r, int x, int y){
if (l > y || r < x){
return Info();
}
if (l >= x && r <= y){
return info[p];
}
int m = (l + r) / 2;
return query(2 * p, l, m, x, y) + query(2 * p + 1, m + 1, r, x, y);
}
Info query(int l, int r){
return query(1, 1, n, l, r);
}
};
void solve(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
pos[a[i]].push_back(i);
}
for(int i=0;i>l>>r;
query[r].emplace_back(l,i);
}
BIT bit(n);
SegmentTree seg(n);
vector cnt(n+1);
for(int i=1;i<=n;i++){
cnt[i]=cnt[i-1];
if(!pos[i].empty()){
cnt[i]++;
seg.modify(pos[i][0],{i});
for(int j=1;j>t;
while(t--) solve();
}