SDOI2008 仪仗队
来源:互联网 发布:温州网络瘫痪 编辑:程序博客网 时间:2024/04/30 03:07
作为体育委员,C君负责这次运动会仪仗队的训练。仪仗队是由学生组成的N * N的方阵,为了保证队伍在行进中整齐划一,C君会跟在仪仗队的左后方,根据其视线所及的学生人数来判断队伍是否整齐(如下图)。
现在,C君希望你告诉他队伍整齐时能看到的学生人数。
共一个数N。
共一个数,即C君应看到的学生人数。
4
9
对于 30% 的数据,1≤N≤1000
对于 100% 的数据,1≤N≤40000
一开始这个题目在CODEVS上的样例输出是错的,让我想了半天,直到佣神帮我把数据改过来。
我们可以把最左下角当作(0,0),然后最右上角自然就是(N-1, N-1),想一想就会发现,如果一个点(X,Y)可以被观测到,那么(KX, KY)就无法被观察到,因为从左下角看过去,这两个点在同一条直线上。
还有一点很容易证明的是,这张图沿着左下-右上这条对角线分开,两部分是对称的,一个比较需要注意的是(1,1)并不属于其中任何一部分,而是在对角线上。
把其中一部分删去后,我们就得到了一个三角形,根据前边标红的性质,对于第N行,我们只需要求出小于等于N且和N互质的正数有多少个就好,这时候我们就可以用到欧拉函数来求解。
把小于等于N且和N互质的数的个数设为phi(N),比如phi(8) = 4,因为1,3,5,7和8互质。
phi(x) = x* (1 - 1/p1) * (1 - 1/p2) ... * (1 - 1/pn)
其中的p1到pn分别为x的n个质因数,需要注意的是,每个质因数只被计算一遍,比如12=2*2*3 phi(12) = 12*(1/2)*(2/3) = 4。
求出phi(2)到phi(n - 1)的和并乘二之后,我们需要特别处理第零列和第零行上的两个点和(1,1)这个点,也就是加上3(第零行和第零列的点可以不特殊处理而是将phi(0)设为1)。
代码如下(求不吐槽风格)
1 #include<iostream> 2 using namespace std; 3 4 int ans, n, a[40001]; 5 6 int main() { 7 cin >> n; 8 n = n - 1; 9 for (int i = 1; i <= n; i++)10 a[i] = i; //PHI(I)11 for (int i = 2; i <= n; i++) //筛法求phi(i)12 if (a[i] == i) {13 int p = 1;14 while (p * i <= n) {15 a[p * i] = a[p * i] / i * (i - 1);16 p++;17 }18 }19 for (int i = 1; i <= n; i++)20 ans += a[i];21 ans = ans * 2 + 1; //(1,1)被计算两次,(0,1)(1,0)没被计算。 22 cout << ans;23 return 0;24 }
- SDOI2008 仪仗队
- SDOI2008 仪仗队
- [SDOI2008]仪仗队
- BZOJ 2818 [SDOI2008] 仪仗队
- 2190: [SDOI2008]仪仗队
- bzoj2190[SDOI2008]仪仗队
- BZOJ 2190 [SDOI2008]仪仗队
- 2190: [SDOI2008]仪仗队
- bzoj 2190: [SDOI2008]仪仗队
- BZOJ 2190: [SDOI2008]仪仗队
- Sdoi2008仪仗队题解
- [BZOJ2190][SDOI2008]仪仗队
- [BZOJ2190][SDOI2008]仪仗队
- 【SDOI2008】【BZOJ2190】仪仗队
- BZOJ2190: [SDOI2008]仪仗队
- bzoj 2190 [SDOI2008]仪仗队
- BZOJ2190: [SDOI2008]仪仗队
- 仪仗队 [Bzoj 2190,SDOI2008]
- 每日一得--spring的bean销毁方法destroy-method="destory"为何不执行
- 用openssl对文件加密及解密
- Android中的Selector的用法
- 145.Binary Tree Postorder Traversal
- 如何选择适合自己的编程语言
- SDOI2008 仪仗队
- 策略模式
- 文章标题
- 批量下载图片文件(服务器端 和 客户端)
- c _alloca 函数的实现
- SDOI2009 晨跑
- delphi 2010 Cannot create file EditorLineEnds.ttr
- 如何成为一名专家级的程序员
- PDF怎么样才能转换成word