2019 Multi-University Training Contest 3
Posted luowentao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2019 Multi-University Training Contest 3相关的知识,希望对你有一定的参考价值。
layout: post
title: 2019 Multi-University Training Contest 3
author: "luowentaoaa"
catalog: true
tags:
mathjax: true
- ACM-ICPC
1004.(二分加线段树DP)
因为二分的值越大 约束条件越少 所以满足二分的性质
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+50;
#define bug cout<<"hehe"<<endl;
int n,k;
ll a[maxn];
ll dp[maxn<<2];
#define ls o<<1
#define rs o<<1|1
void push(int o)
dp[o]=max(dp[ls],dp[rs]);
void build(int o,int l,int r)
if(l==r)
dp[o]=-1e18;return;
int mid=(l+r)/2;
build(ls,l,mid);build(rs,mid+1,r);
push(o);
ll query(int o,int l,int r,int ql,int qr)
if(ql<=l&&qr>=r)return dp[o];
int mid=(l+r)/2;
ll res=-1e18;
if(ql<=mid)res=max(res,query(ls,l,mid,ql,qr));
if(qr>mid)res=max(res,query(rs,mid+1,r,ql,qr));
return res;
void update(int o,int l,int r,int k,ll val)
if(l==r)
dp[o]=val;
return ;
int mid=(l+r)/2;
if(k<=mid)update(ls,l,mid,k,val);
else update(rs,mid+1,r,k,val);
push(o);
ll sum[maxn];
map<ll,int>mp;
map<ll,int>mpp;
vector<ll>ve;
bool check(ll mid)
build(1,0,n+1);
int first=lower_bound(ve.begin(),ve.end(),0)-ve.begin();
update(1,0,n+1,first,0);
for(int i=1;i<=n;i++)
int id=mp[sum[i]];
int ned=lower_bound(ve.begin(),ve.end(),sum[i]-mid)-ve.begin();
// cout<<"ned="<<ned<<" "<<sum[i]-mid<<endl;
ll p=query(1,0,n+1,ned,n+1);
// cout<<"p="<<p<<endl;
// cout<<"id="<<id<<endl;
update(1,0,n+1,id,p+1);
// cout<<"now query="<<query(1,0,n+1,id,id)<<endl;
mp[sum[i]]++;
// cout<<"query="<<query(1,0,n+1,1,n+1)<<endl;
if(query(1,0,n+1,0,n+1)>=k)
return true;
return false;
int main()
int t;
std::ios::sync_with_stdio(false);
cin>>t;
while(t--)
mp.clear();
cin>>n>>k;
ve.clear();
for(int i=1;i<=n;i++)cin>>a[i],sum[i]=sum[i-1]+a[i],ve.push_back(sum[i]);
ve.push_back(0);
sort(ve.begin(),ve.end());
for(int i=0;i<ve.size();i++)
if(mp.count(ve[i])==0)mp[ve[i]]=i;
ll l=-2e15,r=2e15,ans;
mpp=mp;
while(l<=r)
ll mid=(l+r)/2;
mp=mpp;
if(check(mid))
r=mid-1;
ans=mid;
else l=mid+1;
cout<<ans<<endl;
return 0;
1006Fansblog (素数检测 + 威尔逊定理)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e7+50;
ll mod;
ll P;
ll Q;
int prime[maxn+1];
void getprime()
memset(prime,0,sizeof(prime));
for(ll i=2;i<=maxn;i++)
if(!prime[i])prime[++prime[0]]=i;
for(ll j=1;j<=prime[0]&&prime[j]<=maxn/i;j++)
prime[prime[j]*i]=1;
if(i%prime[j]==0)break;
//****************************************************************
// Miller_Rabin 算法进行素数测试
//速度快,而且可以判断 <2^63的数
//****************************************************************
const int S=20;//随机算法判定次数,S越大,判错概率越小
//计算 (a*b)%c. a,b都是long long的数,直接相乘可能溢出的
// a,b,c <2^63
long long mult_mod(long long a,long long b,long long c)
a%=c;
b%=c;
long long ret=0;
while(b)
if(b&1)ret+=a;ret%=c;
a<<=1;
if(a>=c)a%=c;
b>>=1;
return ret;
void print(__int128 x)
if(!x)
puts("0");
return ;
string ret="";
while(x)
ret+=x%10+'0';
x/=10;
reverse(ret.begin(),ret.end());
cout<<ret<<endl;
//计算 x^n %c
long long pow_mod(long long x,long long n,long long mod)//x^n%c
if(n==1)return x%mod;
x%=mod;
long long tmp=x;
long long ret=1;
while(n)
if(n&1) ret=mult_mod(ret,tmp,mod);
tmp=mult_mod(tmp,tmp,mod);
n>>=1;
return ret;
//以a为基,n-1=x*2^t a^(n-1)=1(mod n) 验证n是不是合数
//一定是合数返回true,不一定返回false
bool check(long long a,long long n,long long x,long long t)
long long ret=pow_mod(a,x,n);
long long last=ret;
for(int i=1;i<=t;i++)
ret=mult_mod(ret,ret,n);
if(ret==1&&last!=1&&last!=n-1) return true;//合数
last=ret;
if(ret!=1) return true;
return false;
// Miller_Rabin()算法素数判定
//是素数返回true.(可能是伪素数,但概率极小)
//合数返回false;
bool Miller_Rabin(long long n)
if(n<2)return false;
if(n==2)return true;
if((n&1)==0) return false;//偶数
long long x=n-1;
long long t=0;
while((x&1)==0)x>>=1;t++;
for(int i=0;i<S;i++)
long long a=rand()%(n-1)+1;//rand()需要stdlib.h头文件
if(check(a,n,x,t))
return false;//合数
return true;
__int128 ksm(__int128 a,__int128 b)
__int128 res=1;
a%=mod;
while(b)
if(b&1)res=res*a%mod;
a=a*a%mod;
b>>=1;
return res;
int main()
int t;
// getprime();
std::ios::sync_with_stdio(false);
cin>>t;
while(t--)
ll o;
cin>>o;
P=o;
mod=P;
for(ll i=P-1;;i--)
if(Miller_Rabin(i))
Q=i;
break;
__int128 ans=(-1+mod)%mod;
for(ll i=P-1;i>Q;i--)
ans=ans*ksm(i,mod-2)%mod;
ll u=ans;
cout<<u<<endl;
return 0;
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e7+50;
ll mod;
ll P;
ll Q;
int prime[maxn+1];
void getprime()
memset(prime,0,sizeof(prime));
for(ll i=2;i<=maxn;i++)
if(!prime[i])prime[++prime[0]]=i;
for(ll j=1;j<=prime[0]&&prime[j]<=maxn/i;j++)
prime[prime[j]*i]=1;
if(i%prime[j]==0)break;
bool ok(ll x)
for(int i=1;i<=prime[0];i++)
if(x%prime[i]==0)return false;
return true;
__int128 ksm(__int128 a,__int128 b)
__int128 res=1;
a%=mod;
while(b)
if(b&1)res=res*a%mod;
a=a*a%mod;
b>>=1;
return res;
int main()
int t;
getprime();
std::ios::sync_with_stdio(false);
cin>>t;
while(t--)
ll o;
cin>>o;
P=o;
mod=P;
for(ll i=P-1;;i--)
if(ok(i))
Q=i;
break;
__int128 ans=(-1+mod)%mod;
for(ll i=P-1;i>Q;i--)
ans=ans*ksm(i,mod-2)%mod;
ll u=ans;
cout<<u<<endl;
return 0;
1007Find the answer (简单线段树操作)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+50;
ll a[maxn];
ll tot[maxn];
ll sum[maxn<<2];
ll num[maxn<<2];
#define ls o<<1
#define rs o<<1|1
void push(int o)
sum[o]=sum[ls]+sum[rs];
num[o]=num[ls]+num[rs];
void build(int o,int l,int r)
if(l==r)
sum[o]=0;
num[o]=0;
return;
int mid=(l+r)/2;
build(ls,l,mid);build(rs,mid+1,r);
push(o);
bool update(int o,int l,int r,int k,ll val)
if(l==r)
sum[o]=val;
num[o]=1;
return true;
int mid=(l+r)/2;
if(k<=mid)update(ls,l,mid,k,val);
else update(rs,mid+1,r,k,val);
push(o);
int query(int o,int l,int r,ll val)
// cout<<"o="<<o<<" l="<<l<<" r="<<r<<" val="<<val<<endl;
if(l==r)
return num[o];
int mid=(l+r)/2;
int res=0;
if(sum[rs]==val)return num[rs];
if(sum[rs]<val)
res+=num[rs];
return res+query(ls,l,mid,val-sum[rs]);
else
return query(rs,mid+1,r,val);
map<ll,int>mp;
ll b[maxn];
int main()
int t;
std::ios::sync_with_stdio(false);
cin>>t;
while(t--)
int n,m;
cin>>n>>m;
build(1,1,n);
for(int i=1;i<=n;i++)
cin>>a[i];
tot[i]=tot[i-1]+a[i];
b[i]=a[i];
sort(b+1,b+1+n);
mp.clear();
for(int i=1;i<=n;i++)
// cout<<b[i]<<" ";
if(!mp.count(b[i]))mp[b[i]]=i;
// cout<<endl;
for(int i=1;i<=n;i++)
int id=mp[a[i]];
if(tot[i]<=m)cout<<0<<" ";
else
// cout<<"tot[i]-m"<<tot[i]-m<<endl;
cout<<query(1,1,n,tot[i]-m)<<" ";
update(1,1,n,id,a[i]);
mp[a[i]]++;
cout<<endl;
return 0;
以上是关于2019 Multi-University Training Contest 3的主要内容,如果未能解决你的问题,请参考以下文章
2019 Multi-University Training Contest 6
2019 Multi-University Training Contest 6
2019 Multi-University Training Contest 6
2019 Multi-University Training Contest 3