zoukankan      html  css  js  c++  java
  • POJ 3904 Sky Code

    题意:给定n个数ai, ai <= 10000, n <= 10000, 从中选出4个数要求gcd为1,这样的集合有多少个?

    分析:首先总共集合nCr(n, 4) = n*(n-1)*(n-2)*(n-3)/24个,那么需要减掉gcd >=2 的集合。先减掉gcd为各个素数的方案数目,然后再由这些素数组成一些因子,考虑gcd为这些因子的情况。最后总结起来就是,素数个数为奇数时,减去;素数个数为偶数时,加上。具体实现的时候只要对每个ai分解质因数,然后单独考虑他的素因子能组成哪些数,这样再计算。

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <map>
     4 #include <cstring>
     5 #include <cstdlib>
     6 #include <cmath>
     7 #define pb push_back
     8 #define mp make_pair
     9 #define esp 1e-8
    10 #define lson   l, m, rt<<1
    11 #define rson   m+1, r, rt<<1|1
    12 #define sz(x) ((int)((x).size()))
    13 #define pb push_back
    14 #define in freopen("solve_in.txt", "r", stdin);
    15 #define bug(x) printf("Line : %u >>>>>>
    ", (x));
    16 #define inf 0x7f7f7f7f
    17 using namespace std;
    18 typedef long long LL;
    19 typedef map<int, int> MPS;
    20 typedef pair<int, int> PII;
    21 
    22 const int maxn = 10000 + 10;
    23 int a[maxn];
    24 LL vis[22][maxn], p[22], pa[22];
    25 int cnt;
    26 void dfs(int st, int pos, int lim) {
    27     if(pos == lim) {
    28         int tmp = 1;
    29         for(int i = 0; i < pos; i++)
    30             tmp *= pa[i];
    31         vis[lim][tmp]++;
    32         return;
    33     }
    34     for(int i = st; i < cnt; i++) {
    35         pa[pos] = p[i];
    36         dfs(i+1, pos+1, lim);
    37     }
    38 }
    39 int main() {
    40 
    41     int n;
    42     while(scanf("%d", &n) == 1) {
    43         memset(vis, 0, sizeof vis);
    44         for(int i = 1; i <= n; i++) {
    45             scanf("%d", a+i);
    46             int x = a[i];
    47             cnt = 0;
    48             for(int j = 2; j*j <= x; j++) {
    49                 if(x%j == 0) {
    50                     p[cnt++] = j;
    51                     while(x%j == 0)
    52                         x /= j;
    53                 }
    54             }
    55             if(x != 1)
    56                 p[cnt++] = x;
    57             for(int j = 1; j <= cnt; j++)
    58                 dfs(0, 0, j);
    59         }
    60         double ans = 1.0*n*(n-1)*(n-2)*(n-3)/24;
    61         for(int i = 1; i < 22; i++)
    62             for(int j = 2; j <= 10000; j++)
    63                 if(vis[i][j] >= 4) {
    64                     double tmp = 1.0;
    65                     for(LL k = vis[i][j]; k > vis[i][j]-4; k--)
    66                         tmp = tmp*k;
    67                     tmp /= 24;
    68                     ans += ((i&1) ? -1 : 1)*tmp;
    69                 }
    70         printf("%.0f
    ", ans);
    71     }
    72     return 0;
    73 }
    View Code

     UPD:这题还可以用扩展欧拉函数做?链接:http://scturtle.is-programmer.com/posts/19402.html

    其实是概率角度解释解释欧拉函数,然后拓展一下就可以解这个题了。1/p为包含素因子p的概率。1/p^n为n个数都包含素因子p的概率。

    ans = m^n * ∏(1-1/(p^n))

  • 相关阅读:
    鼠标事件(onmouseover、onmouseout)延时切换插件
    光线跟踪MaxScript版
    MaxSDK添加菜单项
    Linux实战教学笔记03:操作系统发展历程及系统版本选择
    Linux实战教学笔记06:Linux系统基础优化
    Linux实战教学笔记04:Linux命令基础
    Linux实战教学笔记02:计算机系统硬件核心知识
    Linux实战教学笔记05:远程SSH连接服务与基本排错(新手扫盲篇)
    Linux实战教学笔记01:计算机硬件组成与基本原理
    如何启动linux的telnet服务
  • 原文地址:https://www.cnblogs.com/rootial/p/4082340.html
Copyright © 2011-2022 走看看