2018 ACM-ICPC 中国大学生程序设计竞赛线上赛

此生再无相见时 提交于 2021-02-11 06:43:12

2018 ACM-ICPC 中国大学生程序设计竞赛线上赛

[TOC]

A. Death is end

留坑

B.Goldbach

题意

每次给一个偶数$n(n<2<2^{63})$,找出任意两个和为$n$的素数。

分析

从n的$\frac{1}{2}$往两边判素数,使用Miller Rabin随机性素数测试方法。 (ps:自己写了一个虽然过了,但是会被Carmichael数卡掉,还没搞懂板子上的算法怎么搞定Carmichael数的,<font color=red>留坑</font>)

<details><summary> 代码 </summary> ```cpp #include <iostream> #include <cstdio> #include <queue> #include <cstring> #include <vector> #include <map> #include <algorithm> using namespace std; typedef long long ll; const ll MOD=1e9+7; const int maxn=1000500; struct Miller_Rabin { int prime[5]={2,3,5,233,331}; ll qmul(ll x,ll y,ll mod){ ll ans=(x*y-(ll)((long double)x/mod*y+1e-3)*mod); ans=(ans%mod+mod)%mod; return ans; } ll qpow(ll x,ll n,ll mod){ ll ans=1; while(n){ if(n&1) ans=qmul(ans,x,mod); x=qmul(x,x,mod); n>>=1; } return ans; } bool isprime_std(ll p) { if(p < 2) return 0; if(p != 2 && p % 2 == 0) return 0; ll s = p - 1; while(! (s & 1)) s >>= 1; for(int i = 0; i < 5; ++i) { if(p == prime[i]) return 1; ll t = s, m = qpow(prime[i], s, p); while(t != p - 1 && m != 1 && m != p - 1) { m = qmul(m, m, p); t <<= 1; } if(m != p - 1 && !(t & 1)) return 0; } return 1; } bool isprime(ll p){ if(p<2||(p!=2&&p%2==0)) return false; for (int i = 0; i < 5; ++i) { if(p==prime[i]) return true; ll t=qpow(prime[i],p-1,p); if(t!=1) return false; } return true; } }mr; int main(int argc, char const *argv[]) { ll x; while(cin>>x){ printf("%d %d\n", mr.isprime(x),mr.isprime_std(x)); } int t; scanf("%d", &t); while(t--){ ll x; scanf("%lld", &x); if(x==4){ printf("2 2\n"); continue; } ll mid=x/2; if(!(mid&1)) mid--; for (ll i = mid; i >= 0; i-=2) { if(mr.isprime_std(i)&&mr.isprime_std(x-i)){ printf("%lld %lld\n", i,x-i); break; } } } return 0; } ``` </details>

C. Heru and his Monitors

又要留坑-_-|||

D. Merchandise

分析

筛选出素数之后,显然同样大小素数不能分在多个组里,否则无法达到最优。 使用$dp[i][j]$表示前$i$个素数分成$j$组的最小总花费,那么可以得到转移方程 $$dp[i][j]=min(dp[k-1][j-1]+(a[i]-a[k])^2), (1<=k<=i)$$ (ps: 强烈谴责计蒜客的数据,交题的时候必须把$0,1$作为素数,否则就会像我一样浪费两天时间)

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <vector>
#include <cmath>
#include <map>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll MOD=1e9+7;
const int maxn=10500;
const ll inf=0x3f3f3f3f3f3f3f3f;
bool isprime[1<<17];
void get_prime(){
    memset(isprime,true,sizeof isprime);
    // isprime[0]=isprime[1]=false;
    int n=(1<<17);
    for (int i = 2; i < n; ++i)
    {
        if(isprime[i]&&(double)i<=sqrt(n)+1){
            for (int j = i*i; j < n; j+=i)
            {
                isprime[j]=false;
            }
        }
    }
}
ll a[100050],dp[5050][1050];
int q[7050];
double f[7050];
int main(int argc, char const *argv[])
{
    get_prime();
    int t;
    scanf("%d", &t);
    while(t--){
        int r,m;
        scanf("%d%d", &r,&m);
        int n=0;
        for (int i = 0; i < r; ++i)
        {
            int x;
            scanf("%d",&x);
            if(isprime[x]) a[n++]=x;
        }
        sort(a,a+n);
        n=unique(a,a+n)-a;
        for (int i = n; i ; --i)
        {
            a[i]=a[i-1];
        }
        for (int j = 1; j <= m; ++j) dp[0][j]=inf;
        for (int i = 0; i <= n; ++i) dp[i][0]=inf;
        for (int j = 1; j <= m; ++j)
        {
            int h=1,t=0;
            for (int i = 1; i <= n; ++i)
            {
                if(j==1){
                    dp[i][j]=(a[i]-a[1])*(a[i]-a[1]);
                    continue;
                }
                int k=q[t];
                double ff=(double)(dp[i-1][j-1]-dp[k-1][j-1]+a[i]*a[i]-a[k]*a[k])/double(a[i]-a[k]);
                while(t-h+1>=2&&ff<f[t]){
                    t--;
                    k=q[t];
                    ff=(double)(dp[i-1][j-1]-dp[k-1][j-1]+a[i]*a[i]-a[k]*a[k])/double(a[i]-a[k]);
                }
                ++t;
                q[t]=i;
                f[t]=ff;

                while(t-h+1>=2&&(double)2*a[i]>f[h+1]){
                    h++;
                }
                k=q[h];
                dp[i][j]=dp[k-1][j-1]+(a[i]-a[k])*(a[i]-a[k]);
            }
        }
        printf("%lld\n", dp[n][m]);
    }
    return 0;
}

E. Copy and Submit II

太水了略

F. Clever King

$\color{red}{留坑}$

G. Trouble of Tyrant

H. Rock Paper Scissors Lizard Spock

I. Reversion Count

J. Bob's game

K. Ants

L. Nise-Anti-AK Problem

<details> <summary>Click to expand</summary> whatever

html

</details>

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!