• 2018-2019 ACM-ICPC Pacific Northwest Regional Contest (Div. 1)_组队训练


    2018-2019 ACM-ICPC Pacific Northwest Regional Contest (Div. 1)

    Problem A Exam

    题意:两人在做判断题,告诉你一个人有k题时正确的,问第二个人最多有多少题是正确的。

    题解:那我们只要判断一下有多少题是一致的,一致的和k值相比较一下,然后选出最大的,然后不一致的和length-k相比较一下,就可以得出了答案。

    #include<bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof a)
    using namespace std;
    char mp[10][10];
    string s1;
    string s2;
    int main()
    {
        int k;
        cin>>k;
        cin>>s1>>s2;
        int ans = 0;
        for(int i=0;i<s1.size();i++)
        {
            if(s1[i]==s2[i])
            {
                ans++;
            }
        }
        int pp = (ans>=k)?k:ans;
        int qq = (pp==k)?(s1.size()-ans):(s1.size()-k);
        cout<<pp+qq<<endl; 
     } 

    Problem B Coprime Integers

    题意:给出两个区间,问这两区间内能组成有多少组可以组成gcd等于1的组。

    题解:莫比乌斯反演板子题。

    //#include<bits/stdc++.h>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<string>
    #include<vector>
    #include<stack>
    #include<bitset>
    #include<cstdlib>
    #include<cmath>
    #include<set>
    #include<list>
    #include<deque>
    #include<map>
    #include<queue>
    #define ll long long
    #define mod 998244353
    #define pdd pair<double,double>
    #define mem(a,x) memset(a,x,sizeof(a))
    #define IO ios::sync_with_stdio(false);cin.tie(0)
    using namespace std;
    const long long INF = 1e18+5;
    const int inf = 0x3f3f3f3f;  
    const double eps=1e-6;       
    const int MAXN=550005;    
    const double pi=acos(-1);   
    inline char nc() {static char buf[1000000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;}
    inline void read(int &sum) {char ch=nc();sum=0;while(!(ch>='0'&&ch<='9')) ch=nc();while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+(ch-48),ch=nc();}
    const int N = 1e7;
    ll mu[N + 5], p[N + 5];
    bool flg[N + 5];
    void init() {
      int tot = 0;
      mu[1] = 1;
      for (int i = 2; i <= N; ++i) {
        if (!flg[i]) {
          p[++tot] = i;
          mu[i] = -1;
        }
        for (int j = 1; j <= tot && i * p[j] <= N; ++j) {
          flg[i * p[j]] = 1;
          if (i % p[j] == 0) {
            mu[i * p[j]] = 0;
            break;
          }
          mu[i * p[j]] = -mu[i];
        }
      }
      for (int i = 1; i <= N; ++i) mu[i] += mu[i - 1];
    }
    ll solve(int n, int m) {
      ll res = 0;
      for (int i = 1, j; i <= std::min(n, m); i = j + 1) {
        j = std::min(n / (n / i), m / (m / i));
        res += (mu[j] - mu[i - 1]) * (n / i) * (m / i);
      }
      return res;
    }
    int main() {
      int T, a,b,c,d;
      init();
      scanf("%d%d%d%d",&a,&b,&c,&d);
      if(a==1&&c==1)
      {
          cout<<solve(b,d);
      }
      else if(a==1)
      {
          cout<<solve(b,d)-solve(b,c-1);
      }
      else if(c==1)
      {
          cout<<solve(b,d)-solve(a-1,d);
      }
      else
      {
          ll num=solve(b,d)-solve(a-1,d)-solve(b,c-1)+solve(a-1,c-1);
          printf("%lld
    ",num);
      }
      
      return 0;
    }

    Problem C Contest Setting

    题意:给你n道题目,选k题,要问你有多少种不同的选择方法,并且要保证每次选择要不同难度的题。

    题解:简单的dp,先统计一下,每种相同难度系数的有多少种,由于数据不大,我们可以用二维dp,前i个数中挑j个数,如果选择这个数我们就加上dp[i-1][j-1]*mp[i],mp[i]为这个难度的个数,如果不选就为dp[i-1][j],所以我们可以求出状态方程就为dp[i][j] = dp[i-1][j-1]*mp[i]+dp[i-1][j];简而言之,就是在前i个数选j个数就为现在这个选上加不选上的个数。

    #include<bits/stdc++.h>
    #define ll long long int
    #define mem(a,b) memset(a,b,sizeof a)
    using namespace std;
    const int maxn = 1010;
    const int mod =  998244353;
    ll a[maxn];
    map<ll,ll>mp;
    ll num[maxn];
    ll dp[maxn][maxn];
    map<ll,ll>::iterator it;
    int main()
    {
        int n,k;
        cin>>n>>k;
        int count = 0;
        dp[0][0] = 1;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
        }
        sort(a+1,a+n+1);
        for(int i=1;i<=n;i++)
        {
            if(!mp[a[i]])
            {
                mp[a[i]] = ++count;
            }
            num[mp[a[i]]]++;
        }
        for(it = mp.begin();it!=mp.end();it++)
        {
            //cout<<it->first<<endl;
            for(int j=0;j<=k;j++)
            {
                //cout<<it->second<<endl;
                ll tt=dp[it->second-1][j];
                if(j!=0)  tt+=dp[it->second-1][j-1]*num[it->second];
                dp[it->second][j]=(dp[it->second][j]+tt)%mod;
                //cout<<dp[it->second][j]<<endl;
            }
        }
        cout<<dp[count][k]%mod<<endl;
        return 0;
    }

    Problem D Count The Bits

    题意:给你两个数k,b问在1-pow(2,b)-1的范围k的倍数中二进制数的1的个数有多少。

    题解:用数位dp板子带进去就可以解得。

    #include<bits/stdc++.h>
    #define ll long long int 
    #define mem(a,b) memset(a,b,sizeof a)
    using namespace std;
    const int mod = 1e9+9;
    ll dp[130][1200][130];
    ll k,b;
    ll dfs(int cur,int x,int num)
    {
        if(cur == 0)
        {
            return x == 0?num : 0;
        }
        if(dp[cur][x][num]!=-1)
        {
            return dp[cur][x][num];
        }
        ll ans = 0;
        for(int i=0;i<=1;i++)
        {
            ans += dfs(cur-1,(x*2 + i)%k,num+i)%mod;
        }
         return dp[cur][x][num] = ans;
    }
    int main()
    {
        mem(dp,-1);
        cin>>k>>b;
        ll ans = dfs(b,0,0);
        cout<<ans%mod<<endl; 
        return 0;
    } 

    Problem G Goat on a Rope

    题意:给出一个矩形和一个矩形外一点求这点到矩形的最小距离。

    题解:把矩形外分为三种情况,就是在矩形的x轴范围内,和在矩形y轴范围内,然后其余部分。

    #include<bits/stdc++.h>
    using namespace std;
    int t[1010];
    double find(int x,int y,int x1,int x2,int y1,int y2)
    {
        return min(min(sqrt((x-x1)*(x-x1)+(y-y1)*(y-y1)),sqrt((x-x2)*(x-x2)+(y-y1)*(y-y1))),min(sqrt((x-x1)*(x-x1)+(y-y2)*(y-y2)),sqrt((x-x2)*(x-x2)+(y-y2)*(y-y2))));
    }
    int main()
    {
        int x,y,x1,y1,x2,y2;
        cin>>x>>y>>x1>>y1>>x2>>y2;
        int minx = min(x1,x2);
        int maxx = max(x1,x2);
        int miny = min(y1,y2);
        int maxy = max(y1,y2);
        if(x>=minx&&x<=maxx)
        {
            printf("%.3lf",1.0*(min(abs(y-y1),abs(y-y2))));
        }
        else if(y>=miny&&y<=maxy)
        {
            printf("%.3lf",1.0*(min(abs(x-x1),abs(x-x2))));
        }
        else{
            printf("%.3lf",find(x,y,x1,x2,y1,y2));
        }
    }

    Problem H Repeating Goldbachs

    题意:就是给你一个数,可以变成两个质数的之和,然后这个数就变成两个质数的差,并且要保证这两质素差要最大,如果这两数之差小于4,那么就结束递归。

    题解:因为我们给出的数据不大,所以我们先给个欧拉筛筛选出所有的质数,直接递归暴力求解就可以了。

    #include<bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof a)
    #define ll long long int 
    using namespace std;
    const int maxn = 1e6 + 10;
    int prime[maxn];
    int visit[maxn];
    void Prime(){
        mem(visit,0);
        mem(prime, 0);
        for (int i = 2;i <= maxn; i++) {
    //        cout<<" i = "<<i<<endl;
            if (!visit[i]) {
                prime[++prime[0]] = i;      //纪录素数, 这个prime[0] 相当于 cnt,用来计数
            }
            for (int j = 1; j <=prime[0] && i*prime[j] <= maxn; j++) {
    //            cout<<"  j = "<<j<<" prime["<<j<<"]"<<" = "<<prime[j]<<" i*prime[j] = "<<i*prime[j]<<endl;
                visit[i*prime[j]] = 1;
                if (i % prime[j] == 0) {
                    break;
                }
            }
        }
    }
    int ans = 0;
    void dfs(int x,int q)
    {
        if(x<4)
        {
            ans = max(ans,q);
            return;
        }
        for(int i=1;prime[i]<=x-1;i++)
        {
            if(visit[x-prime[i]]==0)
            {
                dfs(abs(x-2*prime[i]),q+1);
                break;
            }
        }
    }
    int main()
    {
        int x;
        Prime();
        cin>>x;
       /* for(int i=1;i<=100;i++)
        {
            cout<<prime[i]<<endl;
        }*/
        dfs(x,0);
        cout<<ans<<endl;
    }

    Problem J Time Limits

    题意:给你n个数,和一个k值求,最大数的k倍整数值。

    #include<bits/stdc++.h>
    using namespace std;
    int t[1010];
    int main()
    {
        int n,s;
        cin>>n>>s;
        for(int i=1;i<=n;i++)
        {
            cin>>t[i];
        }
        sort(t+1,t+n+1);
        cout<<t[n]*s/1000+((t[n]*s)%1000?1:0)<<endl;
    }

    Problem L Liars

    题意:给你n个人对于说实话人数的区间,问你们在这几个人中最多有多少人说了实话。

    题解:暴力枚举说实话的人数,然后判断一下。

    #include<bits/stdc++.h>
    using namespace std;
    int a[1010],b[1010];
    int main()
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i]>>b[i];
        }
        int pp = 0;
        for(int i=0;i<=n;i++)
        {
            int ans = 0;
            for(int j=1;j<=n;j++)
            {
                if(a[j]<=i&&i<=b[j])
                {
                    ans++;
                }
            }
            if(ans == i)
            {
                pp = i;
            }
        }
        if(!pp) puts("-1");
        else{
            cout<<pp<<endl;
        }
    }
  • 相关阅读:
    【小白学PyTorch】1 搭建一个超简单的网络
    【小白学PyTorch】2 浅谈训练集和测试集
    【小白学AI】GBDT梯度提升详解
    【小白学AI】XGBoost推导详解与牛顿法
    【小白写论文】技术性论文结构剖析
    小白学PyTorch 动态图与静态图的浅显理解
    【小白学推荐1】 协同过滤 零基础到入门
    【小白学AI】随机森林 全解 (从bagging到variance)
    OpenCV开发笔记(七十二):红胖子8分钟带你使用opencv+dnn+tensorFlow识别物体
    【python刷题】二叉搜索树-相关题目
  • 原文地址:https://www.cnblogs.com/lcsdsg/p/14395717.html
Copyright © 2020-2023  润新知