zoukankan      html  css  js  c++  java
  • P2480 [SDOI2010]古代猪文

    题目描述

    猪王国的文明源远流长,博大精深。

    iPig 在大肥猪学校图书馆中查阅资料,得知远古时期猪文文字总个数为 \(n\) 。当然,一种语言如果字数很多,字典也相应会很大。

    当时的猪王国国王考虑到如果修一本字典,规模有可能远远超过康熙字典,花费的猪力、物力将难以估量。故考虑再三没有进行这一项劳猪伤财之举

    。当然,猪王国的文字后来随着历史变迁逐渐进行了简化,去掉了一些不常用的字。

    iPig 打算研究古时某个朝代的猪文文字。根据相关文献记载,那个朝代流传的猪文文字恰好为远古时期的 \(1\over k\)

    其中 \(k\)\(n\) 的一个正约数(可以是 \(1\)\(n\))。不过具体是哪 \(1\over k\),以及 \(k\) 是多少,由于历史过于久远,已经无从考证了。

    iPig 觉得只要符合文献,每一种 \(k∣n\) 都是有可能的。他打算考虑到所有可能的 \(k\)。显然当 \(k\) 等于某个定值时,

    该朝的猪文文字个数为 \(n \over k\)。然而从 \(n\) 个文字中保留下 \(n\over k\) 个的情况也是相当多的。iPig 预计,

    如果所有可能的 \(k\) 的所有情况数加起来为 \(p\) 的话,那么他研究古代文字的代价将会是 \(g^p\)

    现在他想知道猪王国研究古代文字的代价是多少。由于 iPig 觉得这个数字可能是天文数字,

    所以你只需要告诉他答案除以 \(999911659\) 的余数就可以了。

    输入格式

    一行两个正整数 n,g。

    输出格式

    输出一行一个整数表示答案。

    输入输出样例

    输入 #1

    4 2

    输出 #1

    2048

    数据范围与提示

    对于 \(10\%\) 的数据 \(1\le n \le 50\)
    对于 \(20\%\) 的数据,\(1\le n \le 1000\)
    对于 \(40\%\) 的数据,\(1\le n \le 10^5\)
    对于 \(100\%\) 的数据,\(1\le n,g \le 10^9\)

    前置芝士

    1. 中国剩余定理(求答案)

    2. 欧拉定理拓展

    3. Lucas定理(求组合数)

    一句话题意 \(g^{\sum_{d|n} C_{n}^{d} \bmod 999911659}\)

    首先,根据欧拉定理的拓展可得

    \(g^{\sum_{d|n} C_{n}^{d}} \bmod 999911659\) = \(g^{\sum_{d|n}C_{n}^{d} \bmod 999911658}\)

    这个题关键就在于求出\(\sum_{d|n}C_{n}^{d} \bmod 999911658\)这个柿子

    看到n的范围那么大,只有卢卡斯定理可以解决这种问题。

    但模数又不是质数,那怎么办呢?

    我们可以考虑对 \(999911658\) 进行因数分解 \(999911658 = 2 \times 3 \times 4679 \times 35617\)

    发现他的因数都是质数,且指数都为1.

    那这么不就可以用Lucas定理求出组合数了吗?

    最后,我们考虑怎么统计答案

    假设,我们计算出\(\sum_{d|n}C_{n}{d}\) mod 2,3,4679,35617 的结果分别为s1,s2,s3,s4

    那么我们可以得到这样一组线性方程

    \[\left\{ \begin{array}{lrc} x \equiv s1 (\bmod 2) \\ x \equiv s2 (\bmod 3) \\ x \equiv s3 (\bmod 4679) \\ x \equiv s4 (\bmod 35617) \end{array} \right. \]

    这样,我们就可以利用中国剩余定理求解出最小的解,然后快速幂算出答案就解决了。

    除此之外,还要特判一下 g = 999911659 的情况

    为毛关于猪的都这么毒瘤(猪国杀,魔法猪学院,古代猪文

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define LL long long
    #define int long long
    int mod = 999911658;
    int g,n,ans,jz[36000],sum[5];
    int p[5] = {0,2,3,4679,35617};
    LL ksm(LL a,LL b,LL p)
    {
    	LL res = 1;
    	for(; b; b >>= 1)
    	{
    		if(b & 1) res = res * a % p;
    		a = a * a % p;
    	}
    	return res;
    }
    LL C(int n,int m,int p)//计算组合数
    {
    	if(n < m) return 0;
    	return jz[n] % p * ksm(jz[m],p-2,p) % p * ksm(jz[n-m],p-2,p) % p;
    }
    LL Lucas(int n,int m,int p)//Lucas定理求组合数
    {
    	if(m == 0) return 1;
    	return C(n%p,m%p,p) * Lucas(n/p,m/p,p) % p;	
    }
    signed main()
    {
    	scanf("%d%d",&n,&g); jz[0] = 1;
    	if(g == 999911659)//特判一下
    	{
    		cout<<0<<endl;
    		return 0;
    	}
    	for(int i = 1; i <= 36000; i++) jz[i] = jz[i-1] * i % mod;//预处理出阶乘
    	for(int i = 1; i * i <= n; i++)//枚举因子
    	{
    		for(int j = 1; j <= 4; j++)
    		{
    			if(i * i == n)
    			{
    				sum[j] = (sum[j] + Lucas(n,i,p[j])) % p[j];//计算出s1,s2,s3,s4
    			}
    			else if(n % i == 0)
    			{
    				sum[j] = (sum[j] + Lucas(n,i,p[j])) % p[j];
    				sum[j] = (sum[j] + Lucas(n,n/i,p[j])) % p[j];
    			}
    		}
    	}
    	for(int i = 1; i <= 4; i++)
    	{
    		ans = (ans + sum[i] * (mod/p[i]) % mod * ksm(mod/p[i],p[i]-2,p[i]) % mod) % mod;//中国剩余定理求解线性同余方程
    	}
    	ans = (ans % mod + mod) % mod; mod++;
    	printf("%lld\n",ksm(g,ans,mod));
    }  
    

    ENDING

  • 相关阅读:
    Docker+Jenkins更换国内插件源
    招聘java工程师
    Apache seaTunnel 数据集成平台
    DBeaver连接MySQL问题的解决
    iphone的mov文件复制到电脑的方法
    IDEA中RestfulToolkit插件的安装及使用
    lwm2m 的notify 的机制
    ALI云接入学习
    CAT1 UIS8910模组对接阿里云平台
    任务的堆栈究竟有何魔力
  • 原文地址:https://www.cnblogs.com/genshy/p/13492496.html
Copyright © 2011-2022 走看看