NOIP培训Day9 [3]苦恼的小明
苦恼的小明
(worry.c worry.pas worry.cpp)
时限1秒
描述:
黄小明和他的合伙人想要创办一所英语培训机构,注册的时候要填一张个人情况的表格,在身高一栏小明犯了愁。
身高要求精确到厘米,但小明实在太高了,无法在纸上填下这么长的数字。小明花钱买通了办事人员,于是只要写上他的身高模10007的结果就行了。
可小明不会取模,想起前几天请你帮他解决了水库的问题,于是又来找你帮忙。
输入:(worry.in)
小明的身高用A1^A2^...^An表示,第一行输入n,第二行输入n个正整数表示A1至An。
输出:(worry.out)
一个数字表示小明身高mod 10007的值。
样例输入: 样例输出:
2 173
17 747
数据范围:
所有的0<=Ai<10000
第1~6数据点满足n=2
第7~10数据点满足n=3
第11个数据点满足n=1234567
(前六个数据会逐渐变大,照顾一下取模没弄清楚的同学。另外没有必要尝试对a1进行0或1的判断来骗分,估计是骗不到的。当然了,如果自认为运气好的人可以试试看,我也阻止不了你。)
题解:
这题其实不难,关键是你要弄明白欧拉函数。
==========================================wikipedia==========================================
(小于等于1的正整数中唯一和1互质的数就是1本身)。
若n是质数p的k次幂,,因为除了p的倍数外,其他数都跟n互质。
欧拉函数是积性函数,即是说若m,n互质,。证明:设A, B, C是跟m, n, mn互质的数的集,据中国剩余定理,
和
可建立双射(一一对应)的关系。因此
的值使用算术基本定理便知,
- 若
- 则
。
其中是使得
整除
的最大整数
(这里
)。
例如
=========================================================================================
所以,我们可以用欧拉函数加上快速幂,来解决这一道题目。
具体代码实现:(By Tony)
/* * Number theory Problem - Eulers Function * Code By TonyFang * Mail To tony-fang@foxmail.com * Copyright TonyFang (in CodeForces) 2013 * All rights reserved. * Copyright TonyFang 2000-2013 (now) * All rights reserved. * worry.cpp / input:worry.in / output:worry.out */ # include <iostream> # include <stdio.h> # include <stdlib.h> # include <string.h> # include <math.h> # include <algorithm> using namespace std; const int MODN = 10007; const int MAXN = 1234568; /*快速幂*/ int POWER(int a,int n,int MO) { int ret = 1, base = a; while(n != 0) { if(n & 1) { ret *= base; ret %= MO; } base *= base; base %= MO; n >>= 1; } return ret % MO; } int main() { freopen("worry.in","r",stdin); freopen("worry.out","w",stdout); /*动态内存分配,节省空间*/ int n,ans,*a,*p,*l; a = new int [MAXN]; p = new int [MODN]; l = new int [MAXN]; memset (p,0,sizeof(p)); memset (l,0,sizeof(l)); /*读取*/ scanf("%d",&n); for (int i = 1;i <= n;i ++) scanf("%d",&a[i]); p[1] = 1; /* 欧拉函数 */ for (int i = 2;i <= MODN;i ++) if (! p[i]) for (int j = i;j <= MODN;j += i) { if (!p[j]) p[j]=j; p[j]=p[j]/i*(i-1); } l[1] = MODN; for (int i = 2;i <= n - 1;i ++) l[i] = p[l[i - 1]]; /* 计算幂(使用快速幂) */ for (int i = n - 1;i >= 1;i --) a[i] = POWER(a[i],a[i + 1],l[i]) + l[i]; printf("%d\n",a[1] % MODN); /*删除已分配的动态内存*/ delete []a; delete []p; delete []l; return 0; }