hdu4048
题意:给定m个数,还有n,n表示有一个长度为n的环,现在要求从M个数中选出若干个数,要求选出的数最大公约数为1,填充在n个位置中,选出的数可以重复,求多少种种方案。旋转当成一样的 。
思路:假设现在选出k个数,满足这k个数gcd为1,那么就是一个k种颜色给长度为n的环染色的问题,也就是经典的polya问题。
接着我们考虑如何使其gcd为1。。我们可以考虑下容斥原理。gcd为1统计一遍,然后减掉gcd为2和3的,gcd为6多减了再加回来,依次类推。大体就是这样。。
值得注意的时,答案要mod 10007,当 n为10007的时候无乘法逆元,就会出问题。所以做的时候要mod (10007 * n),最后答案再 / n. 至于为什么有这个公式。我也不大懂。求数论大神指教。。
下面就是代码:
/*
* Author: yzcstc
* Created Time: 2013/10/26 13:55:35
* File Name: hdu4048.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<utility>
#define M0(x) memset(x, 0, sizeof(x))
#define Inf 0x7fffffff
#define PB push_back
#define SZ(v) ((int)(v).size())
#define maxn 101001
#define maxm 20010
using namespace std;
int n, m, T, M;
int vis[maxm], tot, phi[maxn + ], flag[maxm], cnt[maxm], mm;
vector<int> fac[maxn]; void init(){
for (int i = ; i < maxm; i++) if (!vis[i]) {
flag[i] = ;
for (int j = i * ; j < maxm; j += i) {
if (!vis[j]) vis[j] = flag[j] = ;
else if (flag[j]) flag[j]++;
if (j%(i*i) == ) flag[j] = ;
}
} for (int i = ; i < maxm; ++i)
for (int j = ; j * j <= i; ++j)
if (i % j == ){
fac[i].push_back(j);
if (j * j < i) fac[i].push_back(i / j);
} for (int i = ; i < maxn; ++i) phi[i] = i;
for (int i = ; i < maxn; ++i)
if (phi[i] == i)
for (int j = i; j < maxn; j += i)
phi[j] = phi[j] / i * (i - );
} long long power(long long a, long long b){
long long ret = ;
while (b){
if (b & ) ret = ret * a % M;
a = a * a % M;
b >>= ;
}
return ret;
} long long cal(int l){
long long ret = power(cnt[], l);
for (int i = ; i <= mm; ++i){
if (flag[i] == ) continue;
if (flag[i] & ) ret = (ret - power(cnt[i], l)) % M;
else ret = (ret + power(cnt[i], l)) % M;
}
return ret < ? ret + M : ret;
} void solve(){
scanf("%d%d", &m, &n);
M = n * ;
long long ans = mm = ;
M0(cnt);
int x;
for (int i = ; i <= m; ++i){
scanf("%d", &x);
mm = max(x, mm);
for (int j = ; j < fac[x].size(); ++j)
cnt[fac[x][j]]++;
}
for (int i = ; i * i <= n; ++i)
if (n % i == ){
ans = (ans + cal(i) * phi[n / i]) % M;
if (i * i < n) ans = (ans + cal(n / i) * phi[i]) % M;
}
printf("%I64d\n", (ans % M + M) % M / n);
} int main(){
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
init();
scanf("%d", &T);
while (T--){
solve();
}
//fclose(stdin); fclose(stdout);
return ;
}
hdu4048的更多相关文章
随机推荐
- poj 1182 (关系并查集) 食物链
题目传送门:http://poj.org/problem?id=1182 这是一道关系型并查集的题,对于每个动物来说,只有三种情况:同类,吃与被吃: 所以可以用0,1,2三个数字代表三种情况,在使用并 ...
- ZOJ2412 Farm Irrigation(农田灌溉) 搜索
Farm Irrigation Time Limit: 2 Seconds Memory Limit: 65536 KB Benny has a spacious farm land to ...
- pycharm 创建文件时,自动添加文件头注释
File->settings->Editor->File and Code Templates->Python Script # -*- coding: utf-8 -*- & ...
- android xml解析中的null问题
当我们从服务器或者xml文件加载xml进行解析的时候,往往报告 nullpointer 错误.这是原始代码: String short_name = doc.getElementsByTagName( ...
- libnet 库使用(一)
该库的相关资料主要从源码包中获得(假设当前路径为源码包路径): ./sample 中有代码示例 ./doc/html 中html文件可以通过浏览器打开,参看函数定义 想要的基本上sample中都 ...
- SystemTap 工作原理
<systemtap原理及使用> https://www.cnblogs.com/youngerchina/p/5624588.html 这篇帖子前边系统介绍了systemtap的工作原理 ...
- Spring Boot REST(二)源码分析
Spring Boot REST(二)源码分析 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10117436.html) SpringBoot RE ...
- Android相关概念
2017-06-02 armeabi就是针对普通的或旧的arm v5 cpu,armeabi-v7a是针对有浮点运算或高级扩展功能的arm v7 cpu. armeabi-v7a(32位ARM设备), ...
- Android Studio 小新兵
1. java.lang.IllegalStateException: This app has been built with an incorrect configuration. Please ...
- web前端面试题库
web前端面试题及答案 1.常用那几种浏览器测试?有哪些内核(Layout Engine)? 答: (Q1) 浏览器:IE,Chrome,FireFox,Safari,Opera. (Q2) ...