2020-5-3

 

问题 D: 田忌赛马

时间限制: 1 Sec  内存限制: 128 MB
[提交] [状态]

题目描述

他是一匹棕色的马。他在奔跑,和一群马一起奔跑。
这是那片古老大地上流传着的一个故事,关于马的故事。马之故事,以鞍为墨。
现在,田忌又一次与人赛马。不过不同的是,赛制发生了变化。田忌与对手决定一场定胜负。双方都不能选择自己参赛的马,他们用于一决高下的马将在自己的所有马中随机产生。每一匹马都有一个能力值。能力值较高的马获胜。当两匹马能力值相同时这场比赛被视为平局。
运筹帷幄的田忌不想在未知中等待结果的到来,所以他想知道自己获胜的概率是多少。

输入

第1行一个正整数T,表示数据组数。
对于每组数据,第1行两个正整数N,M,分别表示田忌和对手拥有的马的数量。
第2行N个正整数,第i个正整数Ai表示田忌第i匹马的能力值。
第3行M个正整数,第i个正整数Bi表示对手第i匹马的能力值。

输出

共T行‬对每组数据,一行一个分数,“x/y”(不含引号)
,表示田忌获胜的概率(最简分数)
。

样例输入 Copy

1
3 5
4 3 7
1 9 4 6 10

样例输出 Copy

1/3

提示

样例解释
为方便解释,我们称一组随机选马为二元组(x,y)
,x,y分别代表田忌和对手的马的能力值。
当二元组为(4,1)、(3,1)、(7,1)、(7,4)、(7,6)时,田忌获胜,共5种。
随机选马共有3×5=15种方法。
所以田忌获胜的概率为5/15,化为最简分数为1/3。

对于100%的数据,1≤N,M≤40000;1≤Ai,Bi<109,1≤T≤5

 

 

实在有点坑,注意避免一些重复数据的计算。//cnt,其实也可以优先队列,不过我没试。

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
int a[40005],b[40005],cnt[400005];
int main()
{
  int t;
  scanf("%d",&t);
  while(t--)
  {

      int n,m,kk=0;
      scanf("%d%d",&n,&m);
      memset(a,0,sizeof(a));
      memset(b,0,sizeof(b));
      memset(cnt,0,sizeof(cnt));
      for(int i=1;i<=n;i++)
        scanf("%d",a+i);
      for(int j=1;j<=m;j++)
        scanf("%d",b+j);
      sort(a+1,a+1+n);
      sort(b+1,b+1+m);
      int j=1;
      for(int i=1;i<=n;i++)
      {
          cnt[i]+=cnt[i-1];
          for(;j<=m;)
          {
              if(a[i]>b[j]) cnt[i]++,j++;
              else break;
          }
          kk+=cnt[i];
      }

      int ans=kk;
      int sum=n*m;
     // printf("%d/%d\n",ans,sum);
      while(kk)
      {
          int temp=kk;//sum%cnt
          kk=sum%kk;
          sum=temp;
      }
      printf("%d/%d\n",ans/sum,n*m/sum);
  }
    return 0;
}

问题 A: 埃匹希斯水晶

时间限制: 1 Sec  内存限制: 128 MB
[提交] [状态]

题目描述

⼤家都知道,卡德加是⼀个神奇的法师。
有⼀天,他发现了⼀种可以作⽤在埃匹希斯⽔晶上的魔法:在左右两个祭坛上放⼀定量的⽔晶,然后施放⼀个法术,左边⼀堆的⽔晶数量会变成原来两个祭坛上⽔晶之和,右边⼀堆会变成两个祭坛上⽔晶数量之差。
卡德加现在有两堆⽔晶,分别有A个和B个。他打算集中精⼒连续释放N次法术,但不知道最后能拿到多少⽔晶,于是他找到了要塞指挥官(就是你了)。

输入

三个整数A,B,N(A,B≤109,N≤1018),表⽰祭坛上刚开始的⽔晶数,和法术的释放次数。

输出

两个数,祭坛上最后的⽔晶数。输出模(109+7)。

样例输入 Copy

1 2 3

样例输出 Copy

6 2

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int mod=1e9+7;
int main()
{
  ll a,b,n;
  cin>>a>>b>>n;
  if(a>=b)
  {
      ll cnt=n/2,temp=1;
      while(cnt--)
      {
          temp*=2;
          temp%=mod;
      }
      if(n%2==1)
      {
          printf("%lld %lld",temp*(a+b)%mod,temp*(a-b)%mod);
      }
      if(n%2==0)
      {
           printf("%lld %lld",temp*a%mod,temp*b%mod);
      }
  }
  else
  {
      ll cnt=n/2,temp=1;
      while(cnt--)
      {
          temp*=2;
          temp%=mod;
      }
      if(n%2==1)
      {
          printf("%lld %lld",temp*(a+b)%mod,temp*(b-a)%mod);
      }
      if(n%2==0)
      {
           printf("%lld %lld",temp*b%mod,temp*a%mod);
      }
 
 
  }
    return 0;
}
 
/**************************************************************
    Problem: 15411
    User: 2019UPC110
    Language: C++
    Result: 正确
    Time:267 ms
    Memory:2024 kb
****************************************************************/

 

 

 

 

问题 B: 要塞任务

时间限制: 1 Sec  内存限制: 128 MB
[提交] [状态]

题目描述

你的要塞⾥有N名随从,每名随从有⼀个战⽃⼒值Ai,不同随从的战⽃⼒可以相同,且永远不超过N。⼀个要塞任务需要恰好M个随从参与。
要塞任务的奖励取决于随从们配合的程度。(显⽽易见地),M个随从的联合战⽃⼒A为它们战⽃⼒的最⼤公约数,⽽任务的奖励分数定义为ϕ(A)。
求最⼤可能的奖励分数。

输入

本题有多组数据,第⼀⾏为数据组数T(T≤10)。
接下来每组数据有两⾏,第⼀⾏两个整数N,M,第⼆⾏N个整数Ai(N,M,Ai≤100000)。

输出

最多的奖励分数。

样例输入 Copy

1
5 2
1 4 6 9 12

样例输出 Copy

2

提示

样例解释:派出编号为6和12的随从,联合战⽃⼒为3,奖励分数2。

 

https://blog.csdn.net/sadsummerholiday/article/details/82825252

https://www.cnblogs.com/Droyal/p/7418611.html

欧拉筛,这个处理很棒

 

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
int vis[400005],prim[400005],oul[400005],num[100005],cnt;
void init()
{
    oul[1]=1;//1是1
    for(int i=2; i<=100000; i++)
    {
        if(vis[i]==0)
        {
            prim[++cnt]=i;
            oul[i]=i-1;//其前面有i-1个互质//质数而言
        }
        for(int j=1; prim[j]*i<=100000; j++)
        {
            vis[prim[j]*i]=1;
            if(i%prim[j]==0)
                break;//*
        }

    }
    for(int i=2; i<=100000; i++)
    {
        if(vis[i])
        {
            oul[i]=i;
            int tmp=i;
            for(int j=1; j<=cnt&&tmp>1; j++)
            {
                if(i%prim[j]==0)
                {
                    oul[i]=oul[i]*(prim[j]-1)/prim[j];
                    while(tmp%prim[j]==0)
                        tmp/=prim[j];
                }
                if(prim[j]*2>i)
                    break;
            }
        }
    }

}
int main()
{
    int t,n,m,a,maxn=0;
    cin>>t;
    init();//
    while(t--)
    {
        cin>>n>>m;
        int ans=0;
        memset(num,0,sizeof(num));
        for(int i=1; i<=n; i++)
        {
            cin>>a;
            maxn=max(maxn,a);
            num[a]++;
        }
        for(int i=1; i<=maxn; i++)
        {
            int tmp=0;
            for(int j=i; j<=maxn; j+=i)
            {
                tmp+=num[j];
            }
            if(tmp>=m)
                ans=max(ans,oul[i]);
        }
        cout<<ans<<endl;
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值