有n个数 a
,a
,...,a
Input
一个数n,表示有n个数。(n<=1e15)
Output
一个数,表示好数的个数。
Sample Input
Sample Output
思路:
![](https://i-blog.csdnimg.cn/blog_migrate/37d51c48803b0e18372d65aa4d5809b3.png)
![](https://i-blog.csdnimg.cn/blog_migrate/b54ae41e7f39948a5ef55a4a7658a021.png)
![](https://i-blog.csdnimg.cn/blog_migrate/39b52320cb3c0f79f9492a682602fd8f.png)
开始都是0
现在进行操作 t从1~n依次增加
每次把下标时t的倍数的数都反转(0变成1,1变成0)
如果最后a
![](https://i-blog.csdnimg.cn/blog_migrate/5a3aa65bcf63c6a6abdc0580f265f5ab.png)
为0,那么称此时的i为好数。
现在对于给定的n,求这时候的好数个数。
n<=1e15
2
1
自己可以先以n=8为例模拟一下,就会发现当n的因子(能整除n且小于n的数值)为偶数时会产生一个0;
因此,我们可以遍历小于n的所有数,记录n的因子个数;
找规律代码(并不是AC代码):
#include<stdio.h>
#include<string.h>
using namespace std;
typedef long long ll;
ll n;
int first;
int main(){
ll sum=0,cnt;//记录当前
ll i,j,k;
scanf("%lld",&k);
for(n=1;n<=k;n++){
sum=0;
for(i=1;i<=n;i++){
cnt=0;
for(j=1;j<=i;j++){//寻找i的因子
if(i%j==0) cnt++;
}
if(cnt%2==0) sum++;
}
if(first==sum){
printf("\n");
}
first=sum;
printf("%6lld",sum);
}
return 0;
}
以n=40为例,通过结果可以看出他有一定的规律:
pos代表每行的第一个数字是某个n的答案,pos以1,3,5,7,9,11,13.........递增
sum代表这一行一共几个数字,以2递增
num代表每一行的最后一个数字
/*
pos
0 | 0
1 | 0 1 2
4 | 2 3 4 5 6
9 | 6 7 8 9 10 11 12
16| 12 13 14 15 16 17 18 19 20
25| 20 21 22 23 24 25 26 27 28 29 30
36| 30 31 32 33 34 35
*/
AC代码:
#include<stdio.h>
#include<string.h>
typedef long long ll;
using namespace std;
ll n;
int main(){
scanf("%lld",&n);
ll sum,pos,num;
ll i=0;
sum=pos=num=0;
while(1){
if(pos>=n) break;//走到每一行的最后一个数字
pos+=i*2+1;
sum+=2;
num--;
num+=i*2+1;
i++;
}
for(i=pos;i>n+1;i--){//从后往前找到n的位置
num--;
}
printf("%lld",num);
return 0;
}