• 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==========================================

    varphi(1)=1(小于等于1的正整数中唯一和1互质的数就是1本身)。

    n是质数pk次幂,varphi(n)=varphi(p^k)=p^k-p^{k-1}=(p-1)p^{k-1},因为除了p的倍数外,其他数都跟n互质。

    欧拉函数是积性函数,即是说若m,n互质,varphi(mn)=varphi(m)varphi(n)。证明:设ABC是跟mnmn互质的数的集,据中国剩余定理,A 	imes BC可建立双射(一一对应)的关系。因此varphi(n)的值使用算术基本定理便知,

    n = p_1^{k_1} p_2^{k_2} cdots p_r^{k_r}
    varphi(n) = prod_{i=1}^r p_i^{k_i-1}(p_i-1) = prod_{pmid n} p^{alpha_p-1}(p-1) = nprod_{p|n}left(1-frac{1}{p}
ight)

    其中alpha_p是使得p^{alpha}整除n的最大整数alpha(这里alpha_{p_i} = k_i)。

    例如varphi(72)=varphi(2^3	imes3^2)=2^{3-1}(2-1)	imes3^{2-1}(3-1)=2^2	imes1	imes3	imes2=24

    =========================================================================================

    所以,我们可以用欧拉函数加上快速幂,来解决这一道题目。

    具体代码实现:(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
    ",a[1] % MODN);
    	/*删除已分配的动态内存*/ 
    	delete []a;
    	delete []p;
    	delete []l;
    	return 0;
    }
    
    这篇文章由TonyFang发布。 所有解释权归TonyFang所有。 Mailto: tony-fang@map-le.net
  • 相关阅读:
    Boost练习程序(program_options)
    vim一般设置
    删除文件夹及其子文件
    linux搜索一个文件
    窗口最大最小化
    3dmax 学习
    打造个人电脑安全终极防线
    Cacls Command Question
    vc++学习(六)——代码学习
    学习3dmax(四)
  • 原文地址:https://www.cnblogs.com/TonyNeal/p/sdfzday9_3.html
Copyright © 2020-2023  润新知