[EOJ]2019 ECNU XCPC April Selection #1

solved 3

rank 2

A(博弈)

题意:平面上有形成正n边形的n个点,两个人轮流行动,每次可以连接两个点,但不能和之前的线相交,当连成凸多边形时获胜,问先手胜还是后手胜。

(待填)

B

题意:有一棵奇形怪状的树(不好描述。。),求两个顶点路径的点权和。

找找规律乱搞。。

#include <bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/hash_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define rep(i,n) for(int i=1;i<=n;i++)
#define ll long long
#define pb push_back
#define mp make_pair
#define st first
#define nd second

const int N =1e5 + 7 ;

ll get(ll x){
    ll res=1;
    while((res-1)*2<x){
        res=res*2;
    }
    return res-1;
}

vector<ll> patha,pathb;



int main()
{
    ll a,b,ans=0;
    cin>>a>>b;
    ll fa=get(a),fb=get(b);
    ll aa=fa,bb=fb;
    ll po=(fa+1)/2;
    while(fa!=a){
        patha.pb(fa);
        if(a>fa)fa=fa+po;
        else fa=fa-po;
        po/=2;
    }
    patha.pb(a);

    po=(fb+1)/2;
    while(fb!=b){
        pathb.pb(fb);
        if(b>fb)fb=fb+po;
        else fb=fb-po;
        po/=2;
    }
    pathb.pb(b);

    ll f=-1;

    int i;
    for(i=0;i<min(patha.size(),pathb.size());i++){
        if(patha[i]==pathb[i]){
            f=patha[i];
            continue;
        }
        ans+=patha[i]+pathb[i];
    }

    if(patha.size()>pathb.size())for(;i<patha.size();i++)ans+=patha[i];
    else for(;i<pathb.size();i++)ans+=pathb[i];

    if(f!=-1)ans+=f;

    if(aa>bb)swap(aa,bb);
    while((aa+1)*2<(bb+1)){
        ans+=(aa+1)*2-1;
        aa=(aa+1)*2-1;
    }

    cout<<ans;

    //for(int i=0;i<patha.size();i++)cout<<patha[i]<<endl;
}
View Code

01:51(1A)

C

题意:给出每个面含有的顶点个数,每个顶点所在的面的个数,问是否有这样的正多边形,如果有,输出边数、顶点数和面数。

只有4、6、8、12、20五种正多面体,手玩一下打表。

#include <bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/hash_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define rep(i,n) for(int i=1;i<=n;i++)
#define ll long long
#define pb push_back
#define mp make_pair
#define st first
#define nd second
#define gg cout<<-1<<" "<<-1<<" "<<-1<<endl
const int N =2e6 + 7 ;

int main()
{
    int p,q;
    while(cin>>p>>q){
        if(!p&&!q)break;
        else if(p==3){
            if(q==3)cout<<4<<" "<<6<<" "<<4<<endl;
            else if(q==4)cout<<6<<" "<<12<<" "<<8<<endl;
            else if(q==5)cout<<12<<" "<<30<<" "<<20<<endl;
            else gg;
            continue;
        }
        else if(p==4){
            if(q==3)cout<<8<<" "<<12<<" "<<6<<endl;
            else gg;
            continue;
        }
        else if(p==5){
            if(q==3)cout<<20<<" "<<30<<" "<<12<<endl;
            else gg;
            continue;
        }
        else gg;

    }
}
View Code

02:30(1A)

D

题意:一个-1e100到+1e100的坐标轴,有三种移动方式,每种移动方式p(-1e6<p<1e6)代表可以从x走到x+p,可以走无限步,求能到达的点占所有点的比例。

(待填)

E(欧拉函数)

题意:求L-R的欧拉函数和,L<=R<=4e12,R-L<=1e6

先用线性筛筛出2e6之内的素数,然后用这些素数筛这个区间,利用欧拉函数计算公式即可,筛剩下的数一定是素数。

#include <bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/hash_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define rep(i,n) for(int i=1;i<=n;i++)
#define ll long long
#define pb push_back
#define mp make_pair
#define st first
#define nd second

const int N =1e7 + 7 ;

int prime[N],notprime[N],cnt;

ll a,b;

ll re[N],ans[N];

void euler(int n){
    notprime[1]=1;
    for(int i=2;i<=n;i++){
        if(!notprime[i]){
            prime[++cnt]=i;
        }
        for(int j=1;j<=cnt&&prime[j]*i<=n;j++){
            notprime[i*prime[j]]=1;
            if(i%prime[j]==0){
                break;
            }
        }
    }
}



void euler2(ll l,ll r){
    for(int i=1;i<=cnt;i++){
        for(ll j=l/prime[i]+(l%prime[i]>0);j*prime[i]<=r;j++){
            int f=0;
            while(re[j*prime[i]-l]%prime[i]==0){
                re[j*prime[i]-l]/=prime[i];
                ans[j*prime[i]-l]*=prime[i];
                f=1;
            }
            if(f)ans[j*prime[i]-l]=ans[j*prime[i]-l]/prime[i]*(prime[i]-1);
        }
    }
}

int main()
{
    euler(1e7);
    cin>>a>>b;
    for(int i=0;i<=b-a;i++)re[i]=i+a,ans[i]=1;
    euler2(a,b);
    ll x=0;
    
    for(int i=0;i<=b-a;i++){
        if(re[i]!=1)ans[i]*=re[i]-1;
        x+=ans[i];
    }
    cout<<x;
}
View Code

F

题意:给出一个大于6的这个正整数,把他分解为6个素数的和,保证有解。

小的话就爆搜一下,大的话,偶数分出2 2 2 2,奇数分出2 2 2 3,然后由哥德巴赫猜想,剩下的数一定可以表示成两个素数的和,用Miller-Rabin的板子才行。

#include <bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/hash_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>

using namespace std;
using namespace __gnu_pbds;

#define rep(i,n) for(int i=1;i<=n;i++)
#define ll long long
#define pb push_back
#define mp make_pair
#define st first
#define nd second

const int N =1e7 + 7 ;

ll phi[N],prime[N],sum[N];

int isprime[N],cnt;

int a[]={2,3,7,61,24251};

ll mult_mod(ll a,ll b,ll c){
    a%=c;
    b%=c;
    ll ret=0,tmp=a;
    while(b){
        if(b&1){
            ret+=tmp;
            if(ret>c)ret-=c;
        }
        tmp<<=1;
        if(tmp>c)tmp-=c;
        b>>=1;
    }
    return ret;
}

ll pow_mod(ll a,ll n,ll mod){
    ll ret=1;
    ll tmp=a%mod;
    while(n){
        if(n&1)ret=mult_mod(ret,tmp,mod);
        tmp=mult_mod(tmp,tmp,mod);
        n>>=1; 
    }
    return ret;
}

int check(ll a,ll n,ll x,ll t){
    ll ret=pow_mod(a,x,n);
    ll last=ret;
    rep(i,t){
        ret=mult_mod(ret,ret,n);
        if(ret==1&&last!=1&&last!=n-1)return 1;
        last=ret;
    }
    if(ret!=1)return 1;
    return 0;
}

int MR(ll n){
    if(n<2)return 0;
    if(n==2)return 1;
    if((n&1)==0)return 0;
    ll x=n-1,t=0;
    while((x&1)==0)x>>=1,t++;
    for(int i=0;i<5;i++){
        if(check(a[i],n,x,t))return 0;
    } 
    return 1;
}

void euler(int n){
    phi[1]=1;
    for(int i=2;i<=n;i++){
        if(isprime[i]==0){
            prime[++cnt]=i;
            phi[i]=i-1;
        }
        for(int j=1;j<=cnt&&prime[j]*i<=n;j++){
            isprime[i*prime[j]]=1;
            if(i%prime[j]==0){
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
            else phi[i*prime[j]]=phi[i]*phi[prime[j]];
        }
    }
    for(int i=1;i<=n;i++)sum[i]=sum[i-1]+phi[i];
}

int aa[]={2,3,5,7,11,13,17,19};

int f=0;

int ans[10];

void dfs(int x,int y){
    if(f)return;
    if(x<0)return;
    if(y==7){
        if(x==0){rep(i,6)cout<<ans[i]<<" ";f=1;return;}
        return ;
    }
    for(int i=0;i<8;i++)ans[y]=aa[i],dfs(x-aa[i],y+1);
}


int check(ll x){
    
    }

int main()
{
    ll n;
    euler(1e3);
    int t;
    cin>>t;
    while(t--){
    f=0;
    cin>>n;
    if(n<=20)dfs(n,1);
    else {
        if(n%2==1){
            cout<<2<<" "<<2<<" "<<2<<" "<<3<<" ";
            n-=9;
        }
        else {
            cout<<2<<" "<<2<<" "<<2<<" "<<2<<" ";
            n-=8;
        }
        for(int i=1;i<=cnt;i++){
            if(MR(n-prime[i])>0){
                cout<<prime[i]<<" "<<n-prime[i];
                break;
            }
        }
    }
    cout<<endl;
    }

}
View Code
原文地址:https://www.cnblogs.com/xutianshu/p/10650996.html