集训队寒假集训第二场补题题解

补题什么的待填坑。。。

A - Generous Kefa (语法基础)

直接开桶看看有没有超过k个的,因为题目明确提出没有气球也是可以的

代码

#include <bits/stdc++.h>
using namespace std;
int bk[123213];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n,k;
  cin>>n>>k;
  string a;
  cin>>a;
  for(int i=0;i<a.size();i++)
  {
    bk[a[i]]++;
    if(bk[a[i]]>k)
    return cout<<"NO",0;
  }
  cout<<"YES";
}

B - Godsend(思维)

如果存在一个奇数的话那么第一个就赢否则第二个赢

因为第一个先选如果有奇数且都是奇数那么第一个肯定赢

否则第一个肯定要把所有的偶数选上外加奇数这样凑成奇数

那么如果剩余奇数个奇数他可以全部选上外加偶数那么就是最初的第一种情况

如果剩余偶数个奇数那么选择剩余奇数-1个奇数加上全部偶数这样还是第一个赢

综上所述只要有奇数就是第一个赢

代码

#include <bits/stdc++.h>
using namespace std;
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n;
  cin>>n;
  for(int i=0;i<n;i++)
  {
    int t;
    cin>>t;
    if(t%2!=0)
    return cout<<"First",0;
  }
  cout<<"Second";
}

C - Leha and Function(数学)

数学证明lsr大佬已经给出了证明这里我说一下实现问题

①A序列从小到大排序

②B序列从大到小排序

③记住编号一一映射最后按照原来的B序列输出A序列

代码

#include <bits/stdc++.h>
using namespace std;
struct node
{
  int sum,id;
}b[666666];
int a[666666],c[666666];
bool cmp(node a,node b)
{
  return a.sum>b.sum;
}
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n;
  cin>>n;
  for(int i=0;i<n;i++)
  cin>>a[i];
  for(int i=0;i<n;i++)
  cin>>b[i].sum,b[i].id=i;
  sort(a,a+n);
  sort(b,b+n,cmp);
  for(int i=0;i<n;i++)
  c[b[i].id]=a[i];
  for(int i=0;i<n;i++)
  cout<<c[i]<<" ";
}

F - New Year and Days (思维)

实际上月份的那个好说就是周的那个得看看首先得算一算

实际上就是用ceil(剩余的天数/第一个日期)

当然你也可以看看日历告诉你4有52个那么看一月第一个星期是5开头12月最后一个星期是星期六结尾那么5 6就是53 1 2 3 4 7就是52也可以

最不行的方法你也可以直接去数啊- -

代码

#include <bits/stdc++.h>
using namespace std;
int bk[123213];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n;
  string a,b;
  cin>>n>>a>>b;
  if(b=="week")
  {
    if(n==5||n==6)
    cout<<53;
    else if(n>=1&&n<=4)
    cout<<52;
    else if(n==7)
    cout<<52;
  }
  else if(b=="month")
  {
    if(n<=29)
    cout<<12;
    else if(n==30)
    cout<<11;
    else if(n==31)
    cout<<7;
  }
}

G - New Year and Domino (DP)

解法



转移方程打错了,最后应该是+dp[x1-1][y1-1]

代码

#include <bits/stdc++.h>
using namespace std;
int dp[666][666];
char mp[666][666];
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int n,m;
  cin>>n>>m;
  for(int i=1;i<=n;i++)
  for(int j=1;j<=m;j++)
  {
    cin>>mp[i][j];
    if(mp[i][j]=='.')
    {
      if(mp[i][j-1]=='.')
      dp[i][j]++;
      if(mp[i-1][j]=='.')
      dp[i][j]++;
    }
    dp[i][j]+=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1];
  }
  int q;
  cin>>q;
  while(q--)
  {
    int x1,y1,x2,y2,sum=0;
    cin>>x1>>y1>>x2>>y2;
    for(int i=x1;i<=x2;i++)
    if(mp[i][y1]==mp[i][y1-1]&&mp[i][y1]=='.')
    sum++;
    for(int i=y1;i<=y2;i++)
    if(mp[x1][i]==mp[x1-1][i]&&mp[x1][i]=='.')
    sum++;
    cout<<dp[x2][y2]-dp[x2][y1-1]-dp[x1-1][y2]+dp[x1-1][y1-1]-sum<<"\n";
  }
}

H - New Year and Old Property(位运算)

第二个数的二进制的长度肯定大于等于第一个数二进制的长度

所以我们用位运算去枚举这两个长度之间到底有多少个只包含0的二进制且这个二进制的十进制在这两个数的闭区间内

那么也就是ans=(1<<i)-1-(1<<j)

i in range(len1,len2+1)

j in range(0,i-1)

上面都是python的写法range是一个左闭右开区间

最后看ans在不在两个给定的数的闭区间内即可如果在那么答案+1,最后输出答案

代码(python版本)

a,b=map(int,input().split())
c=bin(a)[2:]
d=bin(b)[2:]
t1=len(c)
t2=len(d)
ans=0
for i in range(t1,t2+1):
    for j in range(0,i-1):
        if ((1<<(i))-1-(1<<j)) in range(a,b+1):
            ans+=1
print(ans)

代码(c++版本)

#include <bits/stdc++.h>
using namespace std;
int len(long long a)
{
  long long sum=0;
  while(a)
  {
    sum++;
    a/=2;
  }
  return sum;
}
int main()
{
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  long long a,b,ans=0;
  cin>>a>>b;
  for(long long i=len(a);i<=len(b);i++)
  for(long long j=0;j<i-1;j++)
  {
    long double n=pow(2,i)-1-pow(2,j);
    if(n>=a&&n<=b)
    ans++;
  }
  cout<<ans;
}
posted @ 2019-01-19 23:25  baccano!  阅读(165)  评论(0编辑  收藏