• 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.  至于为什么有这个公式。我也不大懂。求数论大神指教。。

           下面就是代码:

      1 /*
      2  * Author:  yzcstc
      3  * Created Time:  2013/10/26 13:55:35
      4  * File Name: hdu4048.cpp
      5  */
      6 #include<iostream>
      7 #include<sstream>
      8 #include<fstream>
      9 #include<vector>
     10 #include<list>
     11 #include<deque>
     12 #include<queue>
     13 #include<stack>
     14 #include<map>
     15 #include<set>
     16 #include<bitset>
     17 #include<algorithm>
     18 #include<cstdio>
     19 #include<cstdlib>
     20 #include<cstring>
     21 #include<cctype>
     22 #include<cmath>
     23 #include<ctime>
     24 #include<utility>
     25 #define M0(x) memset(x, 0, sizeof(x))
     26 #define Inf 0x7fffffff
     27 #define PB push_back
     28 #define SZ(v) ((int)(v).size())
     29 #define maxn 101001
     30 #define maxm 20010
     31 using namespace std;
     32 int n, m, T, M;
     33 int vis[maxm], tot, phi[maxn + 10], flag[maxm], cnt[maxm], mm;
     34 vector<int> fac[maxn];
     35 
     36 void init(){
     37       for (int i = 2; i < maxm; i++) if (!vis[i]) {
     38         flag[i] = 1;
     39         for (int j = i * 2; j < maxm; j += i) {
     40             if (!vis[j]) vis[j] = flag[j] = 1;
     41             else if (flag[j]) flag[j]++;
     42             if (j%(i*i) == 0) flag[j] = 0;
     43         }
     44       }
     45       
     46       for (int i = 1; i < maxm; ++i)
     47          for (int j = 1; j * j <= i; ++j)
     48             if (i % j == 0){
     49                    fac[i].push_back(j);
     50                    if (j * j < i) fac[i].push_back(i / j);  
     51             }
     52 
     53       for (int i = 1; i < maxn; ++i) phi[i] = i;
     54       for (int i = 2; i < maxn; ++i) 
     55         if (phi[i] == i)
     56            for (int j = i; j < maxn; j += i)
     57                phi[j] = phi[j] / i * (i - 1);
     58 }
     59 
     60 long long power(long long a, long long b){
     61      long long ret = 1;
     62      while (b){
     63           if (b & 1) ret = ret * a % M;
     64           a = a * a % M;
     65           b >>= 1;      
     66      }
     67      return ret;
     68 }
     69 
     70 long long cal(int l){
     71      long long ret = power(cnt[1], l);
     72      for (int i = 2; i <= mm; ++i){
     73            if (flag[i] == 0) continue;
     74            if (flag[i] & 1) ret = (ret - power(cnt[i], l)) % M;
     75            else ret = (ret + power(cnt[i], l)) % M;
     76      }
     77      return  ret < 0 ? ret + M : ret;
     78 }
     79 
     80 void solve(){
     81      scanf("%d%d", &m, &n);
     82      M = n * 10007;
     83      long long ans = mm = 0;
     84      M0(cnt);
     85      int x;
     86      for (int i = 1; i <= m; ++i){
     87          scanf("%d", &x);
     88          mm = max(x, mm);
     89          for (int j = 0; j < fac[x].size(); ++j)
     90             cnt[fac[x][j]]++;    
     91      }
     92      for (int i = 1; i * i <= n; ++i)
     93         if (n % i == 0){
     94              ans = (ans + cal(i) * phi[n / i]) % M;
     95              if (i * i < n) ans = (ans + cal(n / i) * phi[i]) % M;    
     96         }
     97      printf("%I64d
    ", (ans % M + M) % M / n);
     98 }
     99 
    100 int main(){
    101    // freopen("a.in","r",stdin);
    102    // freopen("a.out","w",stdout);
    103     init();
    104     scanf("%d", &T);
    105     while (T--){
    106          solve();
    107     }
    108     //fclose(stdin); fclose(stdout);
    109     return 0;
    110 }
  • 相关阅读:
    Yantai
    Star War
    douban's woshang
    cannot change font's type in coreldraw
    LuXun said
    WaiTan
    free ubuntu disk前天就收到了寄来的光盘
    Winter Swimming
    before buy laptop买本本前,先来看看
    ubuntu beginer
  • 原文地址:https://www.cnblogs.com/yzcstc/p/3393866.html
Copyright © 2020-2023  润新知