Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

写个解答纪念一下

Posted by syb3181 at 2009-04-20 15:10:18 on Problem 1091
一共有 m ^ n 种,
我们计算有多少个n元组,不满足条件。
如果不满足条件,这 (n + 1)张牌的面值中任意选两个a[i],a[j],(i<>j),记为a,b
那么不定方程 a * x + b * y = 1 无解(否则可以完成任务)。由不定方程的知识,无解的必要条件就是这n + 1个数任意选择两个都互质,也就是说这n + 1个数的最大公约数是1。
关于充分性:
如果这n + 1个数的最大公约数是d,d > 1
任意一种取牌方案,x[i]表示第i种牌取了多少。sigma(a[i] * x[i])是最后的移动步数,它是d的倍数,不为1,得证。

也就是我们要找有多少种取n个数的方法,使得这n个数和m的最大公约数不是1
可以枚举得出m有多少个不同的质因数,m = pi (yi ^ pi),不同的因数是yi,pi表示它的指数,比如 360 = (2 ^ 3) * (3 ^ 2) * (5 ^ 1)
然后应用容斥原理,
举例来说,m = 360, 有 2,3,5这3个不同的质因数
答案 = (m ^ n) - (有公因数2的n元组)- (有公因数3的n元组)- (有公因数5的n元组)+ (有公因数2,3的n元组) -(有公因数2,5的n元组) - (有公因数3,5的n元组)+ (有公因数2,3,5的n元组)。这个比公式形象些。

有公因数d的n元组,每个位置上有 (m/d)个选择(1 ~ m里面有m/d个d的倍数),根据乘法原理,可以得出有公因数d的n元组有 (m/d)^n 个。

有了上面这些,最后就是实现的问题了。我个人一般dfs所有的情况,写个for循环也可以,鉴于本人IQ问题,就不使用位运算。了下面贴个伪代码:
void dfs(int dep,int sum,int per)
{
     if (dep == a.size())
     {
        if (!sum) return;
        bigint tmp(1);
        for (int i = 1;i<=n;i++) tmp *= per;
        //tmp.out();
        if (sum & 1) answer -= tmp;
        else answer += tmp;  
        return;
     }
     b[dep] = 1;
     dfs(dep + 1,sum + 1,per / a[dep]);
     b[dep] = 0;
     dfs(dep + 1,sum,per);
}
per代表每一位上可能的选择数,这个代码加个高精度模板就行了

对了,随便给个数据
5 99999997
9999998500000087275414221566804671288000
1 2 3 4 ..... 好像超过long long了

这么水的题目WA了很久,写个报告纪念一下。

Followed by:

Post your reply here:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator