[TOC]
C
C-Chiaki Sequence Reloaded
https://www.nowcoder.com/acm/contest/142/C
看网上的大佬们找出了规律:在二进制下相邻的两位相同的加一,不相同的减一,然后就用数位 来做了,我数位 本来就很懵逼。。。做了这道感觉又理解了些
对数位 的 模板的理解:
①为什么要在 的时候进行记忆化:
因为其实是有两个状态,一种是完全的,一种是不完全的,而不完全的就要根据每次的情况来计算,就不好记忆化。。
②为什么是 (lim&&i==up)?
因为 就表示数字枚举到最大了,上一次枚举到最大不能表示下一位就不能枚举最大了,比如 ,上一次十位枚举到了 成为最大,那下一位的各位就不能枚举为 了么?并不是呀, 就可以啊,所以要前面所有位都到了最大,下一位才不能枚举成最大
然后就是这道题,大多数的大佬都是通过偏移量来弄的,但是我觉得那样不直观,弄成了 来作为 这样就可以记录负数的下标了
#include"bits/stdc++.h"
using namespace std;
typedef long long LL;
const LL maxn=65+5;
const int MOD=1e9+7;
map<int,LL>dp[70][4]; //dp[pos][0][sta]表示当前弄到pos位,前一位是0,状态为sta
int a[maxn];
LL dfs(int pos,int pre,int sta,bool lim)
{
if(pos==-1)return abs(sta);
if(lim==0&&dp[pos][pre][sta])return dp[pos][pre][sta];
int up=lim?a[pos]:1;
LL cnt=0;
for(int i=0;i<=up;i++)
{
//(i==pre?1:-1)就是看与前一位相不相同,相同就加1,不同就减1
if(pre<=1)cnt+=dfs(pos-1,i,sta+(i==pre?1:-1),lim&&i==up);
else
{
//之前都是前导零,第一位出现1也对答案没贡献,所以sta不变
if(i==1)cnt+=dfs(pos-1,i,sta,lim&&i==up);
//还是没有出现1,pre还是等于2
else cnt+=dfs(pos-1,pre,sta,lim&&i==up);
}
}
cnt%=MOD;
if(lim==0)dp[pos][pre][sta]=cnt;
return cnt;
}
LL solve(LL n)
{
int pos=-1;
while(n)
{
a[++pos]=n&1;
n>>=1;
}
return dfs(pos,2,0,true);
}
int main()
{
int T;
cin>>T;
while(T--)
{
LL N;
scanf("%lld",&N);
printf("%lld\n",solve(N));
}
}
G-Maximum Mode
题意:删除 个数,使得众数唯一,并输出最大的众数
哎~签到题都签不完(;´д`)ゞ
这是lzj童鞋的思路:
把可能成为最大众数的数从大到小排序,然后检查要是符合条件,那么众数就是他了~
怎么检查呢?
先把所有数的次数放在一个 数组里面,然后升序排序
举个栗子: 这个数列
数组就是
然后看 是不是符合条件:
有 个,于是 数组中找到第一个大于等于 的,然后后面的最多只能是 ,表示后面的所有数最多只能出现 次,所以后面至少都要删除
再比如看 行不行:
找到第一个就是 , 数组要从 变成 才能满足 的条件,也就是说 要想成为最大的众数,最少也要删除 个数
#include"bits/stdc++.h"
using namespace std;
typedef long long LL;
const LL maxn=1e5+5;
int b[maxn],sum[maxn];
struct AAA
{
int v,n;
bool operator<(const AAA &a)const
{
return v>a.v;
}
};
AAA a[maxn];
int main()
{
int T;
cin>>T;
while(T--)
{
int N,M;
map<int,int>Mp;
scanf("%d%d",&N,&M);
for(int i=1;i<=N;i++)
{
int t;
scanf("%d",&t);
Mp[t]++;
}
int t=0;
for(map<int,int>::iterator it=Mp.begin();it!=Mp.end();it++)
{
a[t].v=it->first;
a[t].n=it->second;
b[t++]=it->second;
}
sort(a,a+t);
sort(b,b+t);
sum[0]=b[0];
for(int i=1;i<t;i++)sum[i]=sum[i-1]+b[i];
int Max=-1;
for(int i=0;i<t;i++)
{
int pos=lower_bound(b,b+t,a[i].n)-b;
if(sum[t-1]-sum[pos]-(t-1-pos)*(a[i].n-1)<=M)
{
Max=a[i].v;
break;
}
}
cout<<Max<<endl;
}
}