2019 Multi-University Training Contest 3

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;
}
posted @ 2019-07-29 23:47  luowentao  阅读(175)  评论(0编辑  收藏  举报