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的更多相关文章
随机推荐
- node.js 进程崩溃处理
process.on('uncaughtException', (err) => { console.error('有错误'); });
- 关于nodejs 假设httpserver,会发现一次网页打开,服务端会响应两次的问题;
转自:http://cnodejs.org/topic/518772806d38277306804020 每个页面默认都会再发一个de style="line-height: 21px; p ...
- 杭电1133 排队买票 catalan
Buy the Ticket Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)To ...
- 企业官网Web原型制作分享-Tesla
Tesla是汽车行业知名的奢华品牌,产品为纯电动汽车,知名度极高.此模板正是取自Tesla的官网,高端大图配上文字排版,彰显了汽车的奢华感觉. 本原型由国产Mockplus(原型工具)和iDoc(智能 ...
- IOS语法
2017-07-15 NSDictionary里要用到的类型转换 [NSNumber numberWithInt: 89] 2017-12-10 定义一个Block的写法 typedef void ...
- oracle 笔记DBA
1.1oracle开启归档 关闭数据库 SQL>archive log list; SQL>shutdown immediate; SQL>startup mount ; SQL&g ...
- 使用SpringMVC的@CrossOrigin注解解决跨域请求问题
跨域问题,通俗说就是用ajax请求其他站点的接口,浏览器默认是不允许的.同源策略(Same-orgin policy)限制了一个源(orgin)中加载脚本或脚本与来自其他源(orgin)中资源的交互方 ...
- Jetty 9的使用
参考来源:https://www.cnblogs.com/empireghost/p/3522834.html
- 2019.01.09 bzoj3697: 采药人的路径(点分治)
传送门 点分治好题. 题意:给出一棵树,边分两种,求满足由两条两种边数相等的路径拼成的路径数. 思路: 考虑将边的种类转化成边权−1-1−1和111,这样就只用考虑由两条权值为000的路径拼成的路径数 ...
- 2018.12.22 bzoj3926: [Zjoi2015]诸神眷顾的幻想乡(广义后缀自动机)
传送门 题意简述:给出一棵trietrietrie树,每个点表示一个字符,求树上所有路径组成的不同字串数.(叶子数≤20\le 20≤20) 由于有一个神奇的条件,考虑以每一个叶子为树根统计每个点到树 ...