題意:
有N個人排成一排,從1到N按順序依次編號,現在要執行N次操作,第一次操作讓所有的人都蹲下,之後第二次操作讓編號是2和2的倍數的人全部站起來,然後第三次操作讓編號是3和3的倍數的人全部做相反的動作(站着的人蹲下,蹲下的人站起來),以此類推…,最後第N此操作讓編號爲N的這個人也做相反的動作。請問N次操作後,從第A個人到第B個人之間(包括A和B這兩個數字,且A<B)有多少人是站着的?
思路1:(模擬/暴力)
#include<bits/stdc++.h>
using namespace std;
const int inf= 0x3f3f3f3f;
typedef long long ll;
int cn[1000000+10];
void init()
{
memset(cn,-1,sizeof cn); // 1站起來 -1蹲下
for(int i=2;i<=1000000;i++)
{
for(int j=i;j<=1000000;j+=i)
cn[j] = -cn[j];
}
}
int main()
{
int t;cin>>t;
init();
while(t--)
{
int n,a,b;
cin>>n>>a>>b;
int cnt=0;
for(int i=a;i<=b;i++) if(cn[i]==1) cnt++;
cout<<cnt<<endl;
}
}
思路2(找規律):(用前綴和/樹狀數組可以優化時間複雜度)
(n=1 size=1)
(n=2 size=2)
(n=3 size=2)
(n=4 size=3)
(n=5 size=2)
(n=6 size=4)
(n=7 size=2)
(n=8 size=4)
(n=9 size=3)
(n=10 size=4)
(n=11 size=2)
(n=12 size=6)
(n=13 size=2)
(n=14 size=4)
(n=15 size=4)
(n=16 size=5)
(n=17 size=2)
(n=18 size=6)
(n=19 size=2)
(n=20 size=6)
(n=21 size=4)
(n=22 size=4)
(n=23 size=2)
(n=24 size=8)
(n=25 size=3)
(n=26 size=4)
(n=27 size=4)
(n=28 size=6)
因此 易知 若n爲可開方數 則有奇數個因數
#include <stdio.h>
#include <math.h>
int zcs[1000001];
int main()
{
int t, zz;
int i, j, n, a, b;
scanf("%d", &t);
while (t--)
{
int count = 0;
scanf("%d %d %d", &n, &a, &b);
zz = sqrt(n);
for (i = 1; i <= zz; i++)
{
zcs[i * i] = 1;
}
for (i = a; i <= b; i++)
{
if (!zcs[i]) count++;
}
printf("%d\n", count);
}
return 0;
}