2018-2019 ACM-ICPC, Asia Nanjing Regional Contest题解

以下所有AC题解程序来自“仙客传奇”团队。


A. Adrien and Austin

AC的C++语言程序:

#include <iostream>

using namespace std;

int main(void) {
    int n, k;
    scanf("%d%d", &n, &k);
    if (n == 0)
        printf("Austin");
    else if (k == 1)
        printf("%s", n & 1 ? "Adrien" : "Austin");
    else
        printf("Adrien");
    return 0;
}

AC的C++语言程序:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,k;
    while(cin>>n>>k){
        if(n==0) {
            printf("Austin\n");
            continue;
        }
        if(n<=k) {
            printf("Adrien\n");
            continue;
        }
        if(k==1) {
            if(n&1) printf("Adrien\n");
            else printf("Austin\n");
        }
        else {
            printf("Adrien\n");
        }
    }

}



B. Tournament

题解链接:
Gym - 101981B - Tournament 2018icpc南京站现场赛B题
2018 ACM-ICPC 南京站 B Tournament dp+决策单调性+wqs二分



C. Cherry and Chocolate



D. Country Meow

AC的C++语言程序:

#include<bits/stdc++.h>

using namespace std;

const double eps=1e-3;

struct Tpoint{
    double x,y,z;
};

int npoint,nouter;
Tpoint pt[200000],outer[4],res;
double radius,tmp;

inline double dist(Tpoint p1,Tpoint p2)
{
    double dx=p1.x-p2.x,dy=p1.y-p2.y,dz=p1.z-p2.z;
    return (dx*dx+dy*dy+dz*dz);
}

inline double dot(Tpoint p1,Tpoint p2)
{
    return p1.x*p2.x+p1.y*p2.y+p1.z*p2.z;
}

void ball()
{
    Tpoint q[3];
    double m[3][3],sol[3],L[3],det;
    int i,j;
    res.x=res.y=res.z=radius=0;
    switch(nouter){
        case 1:
            res=outer[0];break;
        case 2:
            res.x=(outer[0].x+outer[1].x)/2;
            res.y=(outer[0].y+outer[1].y)/2;
            res.z=(outer[0].z+outer[1].z)/2;
            radius=dist(res,outer[0]);
            break;
        case 3:
            for(int i=0; i<2; ++i){
                q[i].x=outer[i+1].x-outer[0].x;
                q[i].y=outer[i+1].y-outer[0].y;
                q[i].z=outer[i+1].z-outer[0].z;
            }
            for(int i=0; i<2; ++i)for(int j=0; j<2; ++j)
                    m[i][j]=dot(q[i],q[j])*2;
            for(int i=0; i<2; ++i)sol[i]=dot(q[i],q[i]);
            if(fabs(det=m[0][0]*m[1][1]-m[0][1]*m[1][0])<eps)
                return;
            L[0]=(sol[0]*m[1][1]-sol[1]*m[0][1])/det;
            L[1]=(sol[1]*m[0][0]-sol[0]*m[1][0])/det;
            res.x=outer[0].x+q[0].x*L[0]+q[1].x*L[1];
            res.y=outer[0].y+q[0].y*L[0]+q[1].y*L[1];
            res.z=outer[0].z+q[0].z*L[0]+q[1].z*L[1];
            radius=dist(res,outer[0]);
            break;
        case 4:
            for(int i=0; i<3; ++i){
                q[i].x=outer[i+1].x-outer[0].x;
                q[i].y=outer[i+1].y-outer[0].y;
                q[i].z=outer[i+1].z-outer[0].z;
                sol[i]=dot(q[i],q[i]);
            }
            for(int i=0; i<3; ++i)
                for(int j=0; j<3; ++j)m[i][j]=dot(q[i],q[j])*2;
            det=m[0][0]*m[1][1]*m[2][2]
                +m[0][1]*m[1][2]*m[2][0]
                +m[0][2]*m[2][1]*m[1][0]
                -m[0][2]*m[1][1]*m[2][0]
                -m[0][1]*m[1][0]*m[2][2]
                -m[0][0]*m[1][2]*m[2][1];
            if(fabs(det)<eps)return ;
            for(int j=0; j<3; ++j){
                for(int i=0; i<3; ++i)
                    m[i][j]=sol[i];
                L[j]=(m[0][0]*m[1][1]*m[2][2]
                      +m[0][1]*m[1][2]*m[2][0]
                      +m[0][2]*m[2][1]*m[1][0]
                      -m[0][2]*m[1][1]*m[2][0]
                      -m[0][1]*m[1][0]*m[2][2]
                      -m[0][0]*m[1][2]*m[2][1]
                     )/det;
                for(int i=0; i<3; ++i)
                    m[i][j]=dot(q[i],q[j])*2;
            }
            res=outer[0];
            for(int i=0; i<3; ++i){
                res.x+=q[i].x*L[i];
                res.y+=q[i].y*L[i];
                res.z+=q[i].z*L[i];
            }
            radius=dist(res,outer[0]);
    }
}

void minball(int n)
{
    ball();
    if(nouter<4){
        for(int i=0; i<n; ++i)
            if(dist(res,pt[i])-radius>eps){
                outer[nouter]=pt[i];
                ++nouter;
                minball(i);
                --nouter;
                if(i>0){
                    Tpoint Tt=pt[i];
                    memmove(&pt[1],&pt[0],sizeof(Tpoint)*i);
                    pt[0]=Tt;
                }
            }
    }
}

double smallest_ball()
{
    radius=-1;
    for(int i=0; i<npoint; ++i){
        if(dist(res,pt[i])-radius>eps){
            nouter=1;
            outer[0]=pt[i];
            minball(i);
        }
    }
    return sqrt(radius);
}

int main()
{
    while(scanf("%d",&npoint)!=EOF){
        for(int i=0;i<npoint;i++){
            scanf("%lf%lf%lf",&pt[i].x,&pt[i].y,&pt[i].z);
        }
        printf("%.15f\n",smallest_ball());
    }
    return 0;
}



E. Eva and Euro coins

题解链接:
ACM-ICPC 2018 南京赛区现场赛 E. Eva and Euro coins (思维)



F. Frank



G. Pyramid

AC的C++语言程序:

#include <iostream>

using namespace std;

typedef long long ll;
const ll mod = 1e9+7;
const ll inv = 41666667;

int main()
{
    int t;
    ll n;
    scanf("%d",&t);
    while(t-- && scanf("%lld" ,&n) != EOF){
        printf("%lld\n",n * (n+1) % mod * (n+2) % mod * (n+3) % mod * inv % mod);
    }
    return 0;
}

AC的C++语言程序:

#include <iostream>

using namespace std;

typedef long long LL;

const LL MOD = 1e9 + 7;

LL fpm(LL base, LL p) {
    LL ret = 1;
    do {
        if (p & 1) ret = base * ret % MOD;
        base = base * base % MOD;
    } while (p >>= 1);
    return ret;
}

int main(void) {
    int t;
    LL n;
    scanf("%d", &t);
    LL rev24 = fpm(24, MOD - 2);
    while (t--) {
        scanf("%lld", &n);
        printf("%lld\n", n * (n + 1) % MOD * (n + 2) % MOD
            * (n + 3) % MOD * rev24 % MOD);
    }
    return 0;
}

AC的C++语言程序:

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const ll mod=1e9+7;

ll quick_pow(ll a,ll b,ll mod){
    ll ans=1;
    while(b)
    {
        if(b&1) ans=(ans*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return ans;
}

ll inv(ll x,ll mod){
    return quick_pow(x,mod-2,mod);
}

int main(){

    int T;
    scanf("%d",&T);
    while(T--){
        ll n,ans;
        scanf("%lld",&n);
        ans=(((n*(n+1)%mod)*(n+2)%mod)*(n+3)%mod)%mod;
        ans=ans*inv(24,mod)%mod;
        printf("%lld\n",ans);
    }

    return 0;
}



H. Huge Discount

题解链接:
gym 101981H 2018ICPC南京区域赛 H Huge Discount



I. Magic Potion

AC的C++语言程序:

#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
const int inf = 0x7f7f7f7f;
int MM[1500][1500],M[1500][1500],pre[1500],flow[1500],aaaa[510];

int BFS(int s,int t)
{
	queue<int> q;
	q.push(s);
	memset(pre,-1,sizeof(pre));
	flow[s] = inf;
	while(!q.empty())
	{
		int u = q.front();
		q.pop();
		
		for(int v = 0;v <= t;++v)
			if(M[u][v] && pre[v] == -1)
			{
				pre[v] = u;
				flow[v] = min(flow[u],M[u][v]);
				q.push(v); 
			}
	}
	
	if(pre[t] == -1)
		return -1;
	else
		return flow[t];
}

int Maxflow(int s,int t)
{
	int increase,res = 0;
	
	while((increase = BFS(s,t)) != -1)
	{
		int k = t,last = pre[k];
		while(k != s)
		{
			M[last][k] -= increase;
			M[k][last] += increase;
			k = pre[k];last = pre[k];
		}
		res += increase;
	}
	
	return res;
}

int main()
{
	int n,m,k,x,temp,t,ans;
	
	cin>>n>>m>>k;
	t = n + m + 2;
	
	M[0][1] = k;
	for(int i = 1;i <= n;++i)	M[0][i + 1] = 1,M[1][i + 1] = 1;
	for(int i = 1;i <= m;++i)	M[n + i + 1][t] = 1;
	for(int i = 1;i <= n;++i)
	{
		cin>>x;
		for(int j = 0;j < x;++j)
		{
			cin>>temp;
			M[i + 1][temp + n + 1] = 1;
		}
	}	
	ans = Maxflow(0,t);
	cout<<ans<<endl;
	
	return 0;
}

AC的C++语言程序:

#include<bits/stdc++.h>

using namespace std;

const int INF=0x3f3f3f3f;
const int MAX_V=1000+5;

struct edge{
    int to,cap,rev;
    edge(int _to,int _cap,int _rev):to(_to),cap(_cap),rev(_rev){}
};

vector<edge>G[MAX_V];
int level[MAX_V];
int iter[MAX_V];
int n,m,k;

void add_edge(int from,int to,int cap)
{
    G[from].push_back(edge(to,cap,G[to].size()));
    G[to].push_back(edge(from,0,G[from].size()-1));
}

void bfs(int s)
{
    memset(level,-1,sizeof(level));
    queue<int>que;
    level[s]=0;
    que.push(s);
    while(!que.empty()){
        int v=que.front();que.pop();
        for(int i=0;i<G[v].size();i++){
            edge &e=G[v][i];
            if(e.cap>0&&level[e.to]<0){
                level[e.to]=level[v]+1;
                que.push(e.to);
            }
        }
    }
}

int dfs(int v,int t,int f)
{
    if(v==t){
        return f;
    }
    for(int &i=iter[v];i<G[v].size();i++){
        edge &e=G[v][i];
        if(e.cap>0&&level[v]<level[e.to]){
            int d=dfs(e.to,t,min(f,e.cap));
            if(d>0){
                e.cap-=d;
                G[e.to][e.rev].cap+=d;
                return d;
            }
        }
    }
    return 0;
}

int max_flow(int s,int t)
{
    int flow=0;
    for(;;){
        bfs(s);
        if(level[t]<0){
            return flow;
        }
        memset(iter,0,sizeof(iter));
        int f;
        while((f=dfs(s,t,INF))>0){
            flow+=f;
        }
    }
}

int main()
{
    int s,t;
    scanf("%d%d%d",&n,&m,&k);
    for(int i=0;i<n;i++){
        int h,v;
        scanf("%d",&h);
        while(h--){
            scanf("%d",&v);
            add_edge(i+1,v+n,1);
        }
    }
    for(int i=1;i<=n;i++){
        add_edge(0,i,1);
    }
    for(int i=n+1;i<=n+m;i++){
        add_edge(i,n+m+2,1);
    }
    add_edge(0,n+m+1,k);
    for(int i=1;i<=n;i++){
        add_edge(n+m+1,i,1);
    }
    printf("%d\n",max_flow(0,n+m+2));
    return 0;
}



J. Prime Game

AC的C++语言程序:

#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>

using namespace std;

const int N = 1000005;
int n,a[N];
vector<int> pos[N];

void dec(int p){
    int n = a[p];
    for(int i=2; i*i <= n; i++){
        if(n%i == 0){//因子
            pos[i].push_back(p);
            while(n%i == 0)
                n /= i;
        }
    }
    if(n > 1)
        pos[n].push_back(p);
}
int main()
{
    for(int i=2; i<N; i++)
        pos[i].push_back(0);

    scanf("%d",&n);
    for(int i=1; i <= n; i++){
        scanf("%d",&a[i]);
        dec(i);
    }

    long long ans = 0;
    for(int i=2; i < N; i++){
        for(int k=1; k < pos[i].size(); k++)
            ans += (long long)(n-pos[i][k]+1) * (pos[i][k]-pos[i][k-1]);
    }
    cout << ans << endl;
}
//注意:本题是单输入单输出。
//每次只能操作一组数据
/*
 * 第 p个位置上的数,其包含的任意一个素因子
 * 它原本应当产生的贡献有 (n−p+1)*p(n−p+1)*p
 * 但是若其前面出现过一样的素数
 * 那么应当减去一些重复计算的区间。
 * 假设它前面的和它一样的素数,最后一次出现在 q 位置
 * 那么就应当减去 (n−p+1) * q(n−p+1) * q
 * 即 a[p] 包含的任意一个质因子其产生的贡献为 (n−p+1)*p−(n−p+1)*q = (n−p+1)*(p−q)
 * 不妨用 pos[i][k]来存储每个素因子的 “p”
 * pos[i][k−1]存储每个素因子的 “q”。
 * 换句话说,pos[i][k]代表某个素因子 i在 a[1∼n] 中第 k 次“出现”的位置是 pos[i][k]
 * 特别地,令 pos[i][0]=0。
 * 那么对于任意素因子 i,它对答案的贡献是 (n−pos[i][k]+1)*(pos[i][k]−pos[i][k−1])
 * 我们可以对 a[1∼n]分解质因数,然后更新相应的 pos[i][k]
 *
*/

AC的C++语言程序:

#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn = 1e6;
vector<int> vv[maxn + 10];

void euler(int n,int i)
{
    int a = n;
    for(int j = 2;j * j <= a; ++j)
        if(a % j == 0)
        {
        	vv[j].push_back(i);
            while(a % j == 0) 
			 	a /= j;
		}
    if(a > 1)	vv[a].push_back(i);
}

int main()
{
	int n,a;
	for(int i = 2;i < maxn;++i)	vv[i].push_back(0);
	
	cin>>n;
	for(int i = 1;i <= n;++i)
	{
		cin>>a;
		euler(a,i);
	}
	
	ll ans = 0;
	for(int i = 2;i < maxn;++i)
	{
		for(int k = 1;k < vv[i].size();++k)
			ans +=	(ll)(n - vv[i][k] + 1) * (vv[i][k] - vv[i][k - 1]);
	}
	cout<<ans<<endl;
	
	return 0;
}

AC的C++语言程序:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
int f[maxn],prime[maxn],cnt,a[maxn],n;
vector<int> pre[maxn];
vector<int> pos[maxn];
void init()
{
    for(int i=2;i<maxn;i++)
    {
        if(!f[i])
        {
            prime[cnt++]=i;
            pre[i].push_back(i);
        }
        for(int j=0;j<cnt;j++)
        {
            if(i*prime[j]>=maxn)
                break;
            f[i*prime[j]]=1;
            pre[i*prime[j]]=pre[i];
            if(i%prime[j]==0)
                break;
            else
                pre[i*prime[j]].push_back(prime[j]);
        }
    }
}
int main()
{
    init();
    ll ans=0;
    scanf("%d",&n);
    for(int i=1; i<=n; ++i) {
        scanf("%d",a+i);
        for(int j=pre[a[i]].size()-1; j>=0; --j)
            pos[pre[a[i]][j]].push_back(i);
    }
    ans=0;
    for(int i=0; i<cnt; i++) {
        if(pos[prime[i]].size()==0)
            continue;
        ll now=0,tp=0;
        for(int j=0; j<pos[prime[i]].size(); j++) {
            tp+=(pos[prime[i]][j]-now)*(pos[prime[i]][j]-now-1)/2;
            now=(ll)pos[prime[i]][j];
        }
        tp+=(n+1-now)*(n-now)/2;
        ans+=(ll)n*(n+1)/2-tp;
    }
    printf("%lld\n",ans);
    for(int i=0; i<maxn; i++)
        pos[i].clear();
}



K. Kangaroo Puzzle

AC的C++语言程序:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<time.h>
using namespace std;

int main()
{
	char dir[] = {'U','D','L','R'};
	srand(time(NULL));
	int n,m,x;
	x = 50000;
	while(x--)
		putchar( dir[rand() % 4]);	
	
	return 0;
}



L. Lagrange the Chef



M. Mediocre String Problem

题解链接:
Gym - 101981M The 2018 ICPC Asia Nanjing Regional Contest M.Mediocre String Problem Manacher+扩增KMP



参考链接:
ADEGIJKM 2018 ACM-ICPC南京区域赛题解
ADEGIJKM 2018 ACM-ICPC南京区域赛题解

猜你喜欢

转载自blog.csdn.net/tigerisland45/article/details/89738553