Fork me on GitHub

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\n",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;
    }
}

 

posted @ 2021-02-14 11:58  lcsdsg  阅读(138)  评论(0编辑  收藏  举报
【推荐】 程序员网址大全  |  EF CodeFirst  |  百度地图.NET  |  MyNPOI  |  开源  |  我的皮肤  |  ASP.NET MVC4  |  前端提升   |  LINQ   |  WCF   |  EasyUI  |