Codeforces Round 1017 (Div. 4)
ABCD 略
E
统计每一位1的个数,再枚举每个数作为第k个,枚举它每一位和n个数在每一位上^的加减
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
int T,n,a[N],num[31],ss,ans;
void init()
{ans=0;ss=-0x3f3f3f3f3f3f3f;for(int i=0;i<30;i++) num[i]=0;
}
void solve()
{cin>>n;init();for(int i=1;i<=n;i++){cin>>a[i];ans+=a[i];}for(int i=1;i<=n;i++)for(int j=0;j<30;j++){if(a[i]&(1<<j)) num[j]++;}for(int i=1;i<=n;i++){int s=0;for(int j=0;j<30;j++){if(a[i]&(1<<j)) s+=(n-num[j])*(1<<j)-num[j]*(1<<j);}ss=max(ss,s);}cout<<ans+ss<<endl;
}
signed main()
{std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin>>T;while(T--) solve();
}
F
我们如果按照1 2 3 ...k的格式从上到下从左到右填,那么如果m%k!=0,那么相同的两个数永远无法在相邻的上下两格,这样填就行。如果m%k=0,此时,奇数行还按上面的方法填,偶数行,按2 3 ... k 1这样填
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
int T,n,m,k;
void init()
{
}
void solve()
{cin>>n>>m>>k;init();if(m%k){int tot=0;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){++tot;if(tot>k) tot=1;cout<<tot<<" ";}cout<<endl;}return ;}else{for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(i&1){if(j%k==0) cout<<k<<" ";else cout<<j%k<<" ";}else{if((j+1)%k==0) cout<<k<<" ";else cout<<(j+1)%k<<" ";}}cout<<endl;}}
}
signed main()
{std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin>>T;while(T--) solve();
}
G
建立一个双端队列,再设置一个变量表示哪端是头
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
int T,n,Q,x,k,sum,s,q[N*2],l,r,t;
void init()
{sum=s=t=0;l=r=N;
}
void solve()
{cin>>Q;init();cin>>x>>k;q[l]=k;sum=s=k;cout<<sum<<endl;Q--;while(Q--){cin>>x;if(x==3){cin>>k;if(t==0){q[++r]=k;s+=k;sum+=(r-l+1)*k;}else{q[--l]=k;s+=k;sum+=(r-l+1)*k; }cout<<sum<<endl;}if(x==1){if(t==0){sum+=(s-q[r])-(r-l)*q[r];q[--l]=q[r--];}else{sum+=(s-q[l])-(r-l)*q[l];q[++r]=q[l++];}cout<<sum<<endl;}if(x==2){t=1-t;sum=s*(r-l+2)-sum;cout<<sum<<endl;}}
}
signed main()
{std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin>>T;while(T--) solve();
}
H
这段程序的意思是给一个序列a,有q个询问,每个询问包含l,r,k。如果k/a[i]整除就除到不能整除为止累加k`,然后i++,i的范围是l~r。发现最多操作logk次,我们只要算出每次操作的位置,就可以一段一段的算出k的累加值。预处理N范围内所有数的因数,a[i]的范围1e5,我们用一个vector记录a中每个数出现的位置。然后i从l到r遍历,枚举这时的k的所有因数,二分找出这些因数再i~r内出现的最小位置,并找到所有因数最小位置的最小值ri,那么接下来k首先在这个位置进行除操作。在(i,ri-1)内k的值不变,累加,i=ri+1
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int T,n,q,a[N],k,l,r,last,s;
vector<int> b[N],c[N];
void init()
{s=0;
}
void solve()
{cin>>n>>q;init();for(int i=1;i<=n;i++){cin>>a[i];c[a[i]].push_back(i);}while(q--){s=0;cin>>k>>l>>r;last=k;for(int i=l;i<=r;){if(last==1){s+=(r-i+1);break; }int ri=r+1;for(int j=0;j<b[last].size();j++){if(c[b[last][j]].size()){vector<int>::iterator it=lower_bound(c[b[last][j]].begin(),c[b[last][j]].end(),i);if(it!=c[b[last][j]].end()&&*it<=r) ri=min(ri,*it);}}if(ri==r+1){s+=(r-i+1)*last;break;}else{s+=(ri-i)*last;while(last%a[ri]==0) last/=a[ri];s+=last,i=ri+1;}}cout<<s<<endl;}for(int i=1;i<=n;i++) c[a[i]].clear();
}
signed main()
{for(int i=2;i<=N;i++)for(int j=1;j<=N/i;j++){b[i*j].push_back(i);}std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin>>T;while(T--) solve();
}