Codeforces Round #538 (Div. 2) / codeforces1114ABCDEF
B Yet Another Array Partitioning Task
C Trailing Loves (or L'oeufs?)
F Please, another Queries on Array?
A Got Any Grapes?
判断一下即可
#include <bits/stdc++.h>
#include <time.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> P;
//vector<vector<ll> >v;
const int maxn = 2e6 + 5000;
ll n,m;
//ll a[maxn];
ll a,b,c,x,y,z;
int vis[maxn];
int xx[4] = {1,-1,1,-1};
int yy[4] = {-1,1,1,-1};
priority_queue<int,vector<int>,greater<int> >q;
ll ans ;
int main() {
while(cin >> x >> y >> z >> a >> b >> c) {
if(a >= x && b + a - x >= y && b + (a - x) - y + c >= z) {
cout << "YES" << endl;
continue;
}
cout << "NO" << endl;
}
return 0;
}
B Yet Another Array Partitioning Task
给你n个价值,要求分为k段,并且每段求前m大个数,加起来,问最后相加起来sum最大是多少
可以知道,分为k段,取出每段前m个加起来,所以直接排序,求前m * k个便是最大sum,之后
因为需要列出分组情况,标记一下就可以了
#include <bits/stdc++.h>
#include <time.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> P;
//vector<vector<ll> >v;
const int maxn = 2e6 + 5000;
ll n,m,k;
ll a[maxn];
int vis[maxn];
int xx[4] = {1,-1,1,-1};
int yy[4] = {-1,1,1,-1};
priority_queue<pair<ll,ll> >q;
ll ans ;
struct node {
int x,id;
} g[maxn];
int main() {
while(cin >> n >> m >> k ) {
ll sum = 0;
int num = 0,num1 = 0;
memset(vis,0,sizeof(vis));
while(!q.empty()) q.pop();
for(int i = 1; i <= n; i++) {
pair<int,int>p;
cin >> p.first;
p.second = i;
q.push(p);
}
for(int i = 1; i <= m * k; i++) {
ans += q.top().first;
vis[q.top().second] = 1;
q.pop();
}
cout << ans << endl;
int cnt = 0 ;
for(int i = 1; i < n; i++) {
num += vis[i];
if(num == m) {
cout << i << " ";
num = 0;
cnt++;
}
if(cnt == k - 1) break;
}
cout << endl;
}
return 0;
}
C Trailing Loves (or L'oeufs?)
给一个n和b,查询n!在b进制下末尾0的个数
很容易可以想到把b分解质因子,然后对于每个b的质因子,去计数一下看看当前质因子在x中有多少个
另外还要除以一下b是由多少个当前这个质因子构成,对于每个质因子算出来的结果取个min即可
#include <bits/stdc++.h>
#include <time.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> P;
//vector<vector<ll> >v;
const int maxn = 2e6 + 5000;
ll n,m,k;
ll a[maxn];
int vis[maxn];
int xx[4] = {1,-1,1,-1};
int yy[4] = {-1,1,1,-1};
priority_queue<pair<ll,ll> >q;
ll ans ,b;
struct node {
int x,id;
} g[maxn];
ll res(ll x,ll N){
ll sum = 0;
while(N){
sum += N / x, N /= x;
}
return sum ;
}
int main() {
while(cin >> n >> b) {
ans = 1e18;
for(ll i = 2;i * i <= b;i++){
if(b % i == 0){
ll num = 0;
while(b % i == 0) b /= i,num++;
ans = min(ans,res(i,n) / num);
}
}
if(b != 1) ans = min(ans,res(b,n));
cout << ans << endl;
}
return 0;
}
D Flood Fill
n个数,每次使得l到r区间(前提l到r区间所有数必须相等)中的数,变成任意一个数,并且如果变换开始,
那么只能从l到r一直扩增,不能再由其他位置改变,当时没翻译对这个地方,怎么想也想不到做法 哎
如果知道刚刚上个改变方式,对于5000的范围很容易可以想到区间dp,但是由于不能n^3,不需要枚举断点
因为对于一次只能从l到r往其他地方扩展,所以直接枚举区间
有三种状态
对于l + 1到r - 1区间:
如果a[l] == a[r] 那么f[l][r] = f[l + 1][r - 1] + 1,因为很明显只用改变l+1到r-1的数变成a[l]就可以了
如果a[i] != a[r] ,那么有两种状态:f[l][r] = min(f[l + 1][r],f[l][r - 1]) + 1,即先改变l和先改变r取一个最优的
可以写枚举形式,我是直接把区间dp写成记忆化搜索了。
#include <bits/stdc++.h>
#include <time.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> P;
//vector<vector<ll> >v;
const int maxn = 2e6 + 5000;
ll n,m,k;
ll a[maxn];
int vis[maxn];
int xx[4] = {1,-1,1,-1};
int yy[4] = {-1,1,1,-1};
priority_queue<pair<ll,ll> >q;
ll ans ,b;
struct node {
int x,id;
} g[maxn];
ll res(ll x,ll N){
ll sum = 0;
while(N){
sum += N / x, N /= x;
}
return sum ;
}
vector<int>v;
int f[5500][5500];
int dfs(int l,int r){
if(f[l][r] != -1) return f[l][r];
if(l == r) return 0;
int ans;
if(v[l] == v[r]) return f[l][r] = dfs(l + 1,r - 1) + 1;
else return f[l][r] = min(dfs(l + 1,r),dfs(l,r - 1)) + 1;
}
int main() {
while(cin >> n) {
v.clear();
for(int i = 1;i <= n;i++) cin >> a[i];
v.push_back(a[1]);
for(int i = 2;i <= n;i++){
if(a[i] == a[i - 1]) continue;
else v.push_back(a[i]);
}
// for(auto d:v){
// cout << d <<endl;
// }
memset(f,-1,sizeof(f));
cout << dfs(0,v.size() - 1) << endl;
}
return 0;
}
E Arithmetic Progression
交互题:有一个等差数列,要求你找到首项和公差d
你可以有60次操作
q1 : 查询等差数列中第i项的值
q2:查询等差数列中是否存在比x更大的值
交互题一般不是二分就是构造(个人感觉),再不行就是二分加个构造
所以你可以先二分出这个等差数列的上界是多大,因为范围在1e9之间,所以基本上30次就可以二分出边界最大值,
接着去用剩下的次数去查询第i项的值,用最大值gcd = __gcd(Max - a[i],gcd) 变可以得到公差,i可以自己写个随机
函数随机一下,而首项的值就等于Max - (n - 1) * d
#include <bits/stdc++.h>
#include <time.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> P;
vector<vector<ll> >v;
const int maxn = 2e6 + 5000;
ll n,m,ks;
ll a[maxn];
bool vis[maxn];
string str[maxn];
int xx[4] = {1,-1,1,-1};
int yy[4] = {-1,1,1,-1};
int cnt = 60;
int query1(int x){
int val;
cnt--;
cout << "> " << x << endl;
cin >> val;
return val;
}
int query2(int x){
int val;
cout << "? " << x << endl;
cin >> val;
return val;
}
int erfen(int l,int r){
int x ;
while(l <= r){
int mid = (l + r) / 2;
if(query1(mid)){
l = mid + 1;
}else{
r = mid - 1,x = mid;
}
}
return x;
}
long long Rand(double s,double t) {
return s + 1.0*rand()/RAND_MAX*(t-s);
}
int main() {
cin >> n;
srand((unsigned)time(NULL));
int Max = erfen(1,1e9);
int d = 0;
for(int i = 1;i <= cnt;i++){
int num = Rand(1,n + 1);
int dd = query2(num);
d = __gcd(d,Max - dd);
}
cout << "! "<< Max - (n - 1) * d << " " << d << endl;
return 0;
}
F Please, another Queries on Array?
有n个数,两种操作
q1:让l到r区间 * x
q2:查询l到r区间欧拉函数值的乘积
很明显线段树,但是有好多细节
考到的东西还是不少的,
首先对于300里有大约62个素数(如果没记错的话),压位一下,建一棵线段树,然后保存一下乘积和当前这个数与这62个素数或的状态,也放进去,对于q1操作我们需要做的就是转换一下x得到压位后的状态码,然后再l到r区间上乘x,再或上x的状态码,
查询l到r的欧拉函数乘积的时候,需要得到l到r的状态码,即可以知道l到r有那些素数,也可以得到l到r的乘积,直接算是不可以的,我们需要预处理一下62个素数欧拉函数值,另外因为需要mod1e9+7,还要用一下逆元即可
#include <bits/stdc++.h>
#include <time.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int maxn = 4e5 + 5000;
int n,m;
const ll mod = 1e9 + 7;
int sum = 0;
ll Stauts[maxn];
int prime[5000];
bool isprime[5000];
int cnt = 1;
ll a[maxn];
struct node {
int l,r;
int valu;//值
int lazy;//懒惰乘积
ll Statuslazy;//往下传递的
ll Status;//自己的
} no[maxn<<2];
ll f[65];
ll qpow(ll x,ll y) {
ll ans=1;
while(y) {
if(y&1)
ans=(1ll*ans*x)%mod;
x=(1ll*x*x)%mod;
y=y>>1;
}
return ans;
}
void pushup(int id,node a,node b) {
no[id].valu=1ll*a.valu*b.valu%mod;
no[id].Status=1ll*a.Status|b.Status;
}
int cur = 1;
void build(int id,int l,int r) {
no[id].l=l;
no[id].r=r;
no[id].lazy=1;
no[id].Statuslazy=0;
no[id].Status=0;
if(l==r) {
no[id].valu = a[cur] ;
no[id].Status |= Stauts[cur];
// cout << Stauts[cur]<< endl;
cur++;
return ;
}
int mid=(l+r)/2;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
pushup(id,no[id<<1],no[id<<1|1]);
}
void pushdown(int id,ll x,ll y) {
if(no[id].lazy) {
no[id<<1].lazy=(1ll*no[id<<1].lazy*x)%mod;
no[id<<1|1].lazy=(1ll*no[id<<1|1].lazy*x)%mod;
no[id<<1].Statuslazy|=y;
no[id<<1|1].Statuslazy|=y;
no[id<<1].Status|=y;
no[id<<1|1].Status|=y;
no[id<<1].valu=(1ll*no[id<<1].valu*qpow(x,no[id<<1].r-no[id<<1].l+1))%mod;
no[id<<1|1].valu=(1ll*no[id<<1|1].valu*qpow(x,no[id<<1|1].r-no[id<<1|1].l+1))%mod;
no[id].lazy=1;
no[id].Statuslazy=0;
}
}
void update(int id,int l,int r,ll x,ll y) {
if(no[id].l>=l && no[id].r<=r) {
no[id].valu=(1ll*no[id].valu*qpow(x,no[id].r-no[id].l+1))%mod;
no[id].Statuslazy|=y;
no[id].Status|=y;
no[id].lazy=(1ll*no[id].lazy*x)%mod;
return ;
}
pushdown(id,no[id].lazy,no[id].Statuslazy);
int mid=(no[id].l+no[id].r)/2;
if(l<=mid)
update(id<<1,l,r,x,y);
if(r>mid)
update(id<<1|1,l,r,x,y);
pushup(id,no[id<<1],no[id<<1|1]);
}
node query(int id,int l,int r) {
if(no[id].l>=l && no[id].r<=r) {
return no[id];
}
pushdown(id,no[id].lazy,no[id].Statuslazy);
int mid=(no[id].l+no[id].r)/2;
if(r<=mid)
return query(id<<1,l,r);
if(l>mid)
return query(id<<1|1,l,r);
node xx,yy;
xx=query(id<<1,l,r);
yy=query(id<<1|1,l,r);
xx.valu=(1ll*xx.valu*yy.valu)%mod;
xx.Status=(1ll*xx.Status|yy.Status);
return xx;
}
ll inv[1000020];
void Init() {
memset(isprime,0,sizeof(isprime));
isprime[1] = isprime[0] = 1;
for(int i = 2; i <= 500; i++) {
if(!isprime[i]) {
prime[cnt++] = i;
for(int j = i + i; j <= 500; j += i)
isprime[j] = 1;
}
}
memset(inv,0,sizeof(inv));
inv[1]=1;
for(int i=2; i<1000; i++)
if(!inv[i])
for(int j=i; j<1000; j+=i) {
if(!inv[j])
inv[j]=j;
inv[j]=inv[j]/i*(i-1);
}
inv[1]=1;
for(int i=2;i<=300;i++)
inv[i]=mod-1ll*(mod/i)*inv[mod%i]%mod;
for(int i=1;i<cnt;i++)
f[i]=1ll*inv[prime[i]]*(prime[i]-1)%mod;
return ;
}
ll getvalue(ll x) {
ll res = 0;
for(ll i = 1; prime[i] <= x; i++) {
if(! (x % prime[i]))
res |= (1ll << (i - 1ll));
}
return res;
}
int main() {
Init();
int q;
// cout << prime[63] << endl;
while(cin >> n >> q) {
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= n; i++) {
Stauts[i] = getvalue(a[i]);
}
build(1,1,n);
while(q--) {
string op;
int l,r,x;
cin >> op;
if(op[0] == 'T') {
cin >> l >> r;
node g = query(1,l,r);
ll stat = g.Status;
// cout << g.Status <<endl;
ll ans = g.valu ;
// cout << ans << endl;
for(int i = 0; i <= 62; i++) {
if(stat & (1ll << i)) {
// cout << prime[i + 1] << endl;
// cout << inv[prime[i + 1]] << endl;
ans *= f[i + 1];
// cout << f[i + 1] << endl;
ans %= mod;
}
}
cout << ans % mod << endl;
} else {
cin >> l >> r >> x;
ll value = getvalue(x);
update(1,l,r,x,value);
}
}
}
return 0;
}
//void update(int id,int l,int r,ll x,ll y)