Gym-101982(2018 ICPC Pacific Northwest Regional Contest)

2018 ICPC Pacific Northwest Regional Contest

  • A
  • B
  • C
  • D
  • E
  • F
  • G
  • H
  • I
  • J
  • K
  • L
  • M

A

题意:两个人各选择了n个答案(T或F),第二个人的答案有k个是对的,找出第一个人答案正确的最大数量。

题记:分为两种情况,两个人选的答案相同,那么第二个人正确则第一个人也正确。两个人选的答案不同,第二个人答案错误第一个人则正确。

#include

using namespace std;

int main(){
    int k;
    cin>>k;
    string s1,s2;
    cin>>s1>>s2;
    int a=0,b=0,ans=0;
    for(int i=0;i<s1.size();i++){
        if((s1[i]=='T'&&s2[i]=='T')||(s1[i]=='F'&&s2[i]=='F'))
            a++;
        else
            b++;
    }
    if(k<=a) ans=k+b;
    else ans=a+b-(k-a);
    cout<<ans<<endl;
    return 0;
}

B

题意:莫比乌斯反演模板题。

题记:略

#include
#include
#include
#include
#include
using namespace std;
#define ll long long
const int N = 1e7+2;
const int mod = 1e9 + 7;
const int MAXN = 1e7+2;
bool check[MAXN + 10];
int prime[MAXN + 10];
int mu[MAXN + 10];
void Moblus()
{
    memset(check, false, sizeof(check));
    mu[1] = 1;
    int tot = 0;
    for (int i = 2; i <= MAXN; i++)
    {
        if (!check[i])
        {
            prime[tot++] = i;
            mu[i] = -1;
        }
        for (int j = 0; j < tot; j++)
        {
            if (i * prime[j] > MAXN) break;
            check[i * prime[j]] = true;
            if (i % prime[j] == 0)
            {
                mu[i * prime[j]] = 0;
                break;
            }
            else
            {
                mu[i * prime[j]] = -mu[i];
            }
        }
    }
}
int sum[MAXN + 10];
//找[1,n],[1,m]内互质的数的对数
long long solve(int n, int m)
{
    long long ans = 0;
    if (n > m)swap(n, m);
    for (int i = 1, la = 0; i <= n; i = la + 1)
    {
        la = min(n / (n / i), m / (m / i));
        ans += (long long)(sum[la] - sum[i - 1]) * (n / i) * (m / i);
    }

    return ans;
}
int main()
{
    Moblus();
    sum[0] = 0;
    for (int i = 1; i <= MAXN; i++)
        sum[i] = sum[i - 1] + mu[i];
    int a, b, c, d, k;
    int T;
    scanf("%d%d%d%d", &a, &b, &c, &d);
   long long ans = solve(b, d) - solve((a - 1), d) - solve(b , (c - 1))
          + solve((a - 1), (c - 1));
        printf("%lld\n", ans);
    
    return 0;
}

C

题意:找出k个不同难度的题为一个方案,问有多少个方案。

题记:用dp来做,dp[i][j]表示的是前i种数选j个的方案数,由于每次循环只用到i-1的方案数,可以用滚动数组优化。

#include

using namespace std;
typedef long long ll;
const int N=1010,MOD=998244353;
ll dp[N];
map<int,int>mp;
int main(){
    int n,k;
    cin>>n>>k;
    for(int i=1;i<=n;i++){
        int x;
        cin>>x;
        mp[x]++;
    }
    map<int,int>::iterator it=mp.begin();
    int sz=mp.size();
        dp[0]=1;
    for(int i=1;i<=sz;i++){
        for(int j=k;j>=1;j--)
            dp[j]=(dp[j-1]*(it->second)+dp[j])%MOD;
        it++;
    }
    cout<<dp[k]<<endl;
    return 0;
}

D

E

F

G

题意:给出屋子的两个对称坐标的和羊的坐标,求羊在不碰到屋子的情况下羊绳最长的长度。

题记:先把屋子画为一个矩形,分为两种情况,一种是羊到矩形的边距离最短,一种是羊到矩形的点距离最短。

#include

using namespace std;

double cal(double x1, double y1, double x2, double y2)
{
    return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}

int main(){
    double ans;
    double x, y, x1, x2, y2, y1;
    cin >> x >> y >> x1 >> y1 >> x2 >> y2;
    if (x >= min(x1, x2) && x <= max(x2, x1))
        ans = min(abs(y1 - y), abs(y2 - y));
    else if (y >= min(y1, y2) && y <= max(y1, y2))
        ans = min(abs(x - x1), abs(x - x2));
    else
        ans = min(cal(x, y, x1, y1), min(cal(x, y, x2, y2), min(cal(x, y, x1, y2), cal(x, y, x2, y1))));
    printf("%.3f\n",ans);
    return 0;
}

H

题意:给出一个x,分解x为一对质数(两个质数相加等于x),如果有多对,取差值最大的一对。取这两个数的差值继续做上面的操作,直到x小于4。

题记:打表素数,然后对于遍历素数,判断x-当前素数是否素数即可。

#include

using namespace std;
const int N=1e6;
bool vis[N+10];
int primes[N],cnt;
//朴素筛法
/*
void get_primes(int n)
{
    for (int i = 2; i <= n; i ++ )
    {
        if (vis[i]) continue;
        primes[cnt ++ ] = i;
        for (int j = i + i; j <= n; j += i)
            vis[j] = true;
    }
}
*/
//线性筛法
void get_primes(int n)
{
    for (int i = 2; i <= n; i ++ )
    {
        if (!vis[i]) primes[cnt ++ ] = i;
        for (int j = 0; primes[j] <= n / i; j ++ )
        {
            vis[primes[j] * i] = true;
            if (i % primes[j] == 0) break;
        }
    }
}

int main(){
    get_primes(N);
    int x;
    cin>>x;
    int ans=0;
    while(x>=4){
        for(int i=0;i<cnt;i++){
            if(vis[x-primes[i]]==false){
                //cout<
                x=x-primes[i]-primes[i];
                ans++;
                break;
            }
        }
        //cout<
    }
    cout<<ans<<endl;
    return 0;
}

I

J

题意:给出n个时间(毫秒 )和s倍,求以整数秒限制的t。

题记:找出最大的时间,乘上s然后向上取整即可。

#include

using namespace std;
typedef long long ll;
const int N=110;
int a[N];
int main(){
    int n,s;
    cin>>n>>s;
    for(int i=0;i<n;i++)
        cin>>a[i];
    sort(a,a+n);
    cout<<(a[n-1]*s+999)/1000<<endl;
    return 0;
}

K

L

M

剩下题目待补。。。

你可能感兴趣的:(codeforces)