开心数
题目地址
2021-04-03 22:40:34 星期六
这题的数据范围时l,r <= 10^18所以简单的模拟是不能ac的,时间主要花费在每个数都要求一遍二进制来判断是否只有一个0位,所以可以预先处理出所有开心数,遍历真个开心数来判断是否在l,r这个区间范围内即可,那么整个问题变成如何预处理出开心数。
找出所有在二进制表示的情况下,所有位数都为1的数。然后拿这些数分别减2的次幂(其指数比该数的>找出所有在二进制表示的情况下,所有位数都为1的数。然后拿这些数分别减2的次幂(其指数比该数的 最高位数低)的所有情况,一 一列举
code
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll; // 10^18要开long long
ll log2_[61]={1}; // 存2的n次幂 例如2 4 8 16...2^61
ll m[2000]; //存储开心数
int cnt=1; // 开心数数组的下标
void init()
{
for(int i=1;i<61;i++) //求2的n次幂 初始化首元素为1
log2_[i]=log2_[i-1]*2;
for(int i=2;i<61;i++)
{
for(int j=i-2;j>=0;j--)
{
m[cnt++]=log2_[i]-1-log2_[j];
// log2_[i]-1 求出所有位数为1的数
// 111-(10)=101 即可求出一个开心数
}
}
}
int main()
{
init();
int t;
cin>>t;
while(t--)
{
ll l,r;
cin>>l>>r;
int res=0;
int pos=0;
for(int i=1;i<=cnt;i++)
{
if(m[i]<=r&&m[i]>=l)res++;
if(m[i]>r)break;
}
cout<<res<<endl;
}
return 0;
}
开心整数
需要注意0!=1
code
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1000010;
bool st[N];
long long a[15];
//
void dfs(int n,int p)//n为题目输入的数,p为某个数的阶乘
{
if(p==-1)return;
st[n+a[p]]=1;
dfs(n+a[p],p-1);//加上当前的数的阶乘
dfs(n,p-1);//不加当前数的阶乘
}
int main()
{
int n;
a[0]=a[1]=1;
for(int i=2;i<10;i++) // 处理0-9的阶乘
a[i]=a[i-1]*i;
dfs(0,9);
while(scanf("%d",&n),n>=0)
{
if(st[n])
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
以失败告终!
浙公网安备 33010602011771号