zoukankan      html  css  js  c++  java
  • POJ1091跳蚤(容斥 + 唯一分解 + 快速幂)

     

     题意:规定每次跳的单位 a1, a2, a3 …… , an, M,次数可以为b1, b2, b3 …… bn, bn + 1, 正好表示往左,负号表示往右, 求能否调到左边一位,即 a1* b1+ a2 * b2 + a3 * b3 + …… + m * (bn + 1) = 1;

    根据欧几里得,则a1, a2 a3 …… an, m 最大公约数为1,m已知且a1, a2, a3 …… an 均小于等于m, 一共有m ^ n可能, 将m 唯一分解之后, 假设m = 2 * 3 * 5, 则不大于m且包含2因子的 共 m / 2, 包含3的 为 m/ 3, 容斥

     1 #include <iostream>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <cstdio>
     5 using namespace std;
     6 const int Max = 10000 + 10;
     7 typedef long long LL;
     8 LL n, m;
     9 int prime[Max + 10], vis[Max + 10], tot;
    10 LL em[100], a[100], cnt;
    11 LL res;
    12 void getPrime()
    13 {
    14     tot = 0, cnt = 0;
    15     memset(vis, 0, sizeof(vis));
    16     for (int i = 2; i <= Max; i++)
    17     {
    18         if (!vis[i])
    19         {
    20             prime[tot++] = i;
    21             for (int j = i; j <= Max / i; j++)
    22                 vis[i * j] = 1;
    23         }
    24     }
    25 
    26 }
    27 void getfactor(int b)
    28 {
    29     memset(em, 0, sizeof(em));
    30     for (int i = 0; i < tot; i++)
    31     {
    32         if (prime[i] > b)
    33             break;
    34         if (b % prime[i] == 0)
    35         {
    36             em[cnt++] = prime[i];
    37             while (b % prime[i] == 0)
    38             {
    39                 b /= prime[i];
    40             }
    41         }
    42     }
    43     if (b > 1)
    44         em[cnt++] = b;
    45 }
    46 LL Pow(LL a, LL b)
    47 {
    48     LL ans = 1;
    49     while (b > 0)
    50     {
    51         if (b & 1)
    52             ans *= a;
    53         b >>= 1;
    54         a *= a;
    55     }
    56     return ans;
    57 }
    58 void dfs(int cur, int num, int Cnt)  // cur当前位置, num当前已包含个数,Cnt目标个数
    59 {
    60     if (num == Cnt)
    61     {
    62 //达到目标个数时, 用 m 去除以 所有包含的数
    63         LL u = m;
    64         for (int i = 0; i < num; i++)
    65             u /= a[i];
    66         res += Pow(u, n);
    67         return;
    68     }
    69     for (int i = cur; i < cnt; i++)
    70     {
    71         a[num] = em[i];
    72         dfs(i + 1, num + 1, Cnt);
    73     }
    74     return;
    75 }
    76 int main()
    77 {
    78     getPrime();
    79     while (scanf("%I64d%I64d", &n, &m) != EOF)
    80     {
    81         getfactor(m);
    82         LL sum = Pow(m, n);
    83         for (int i = 1; i <= cnt; i++) // 枚举每一个组合,i表示每个组合中数的个数
    84         {
    85             res = 0;
    86             dfs(0, 0, i);
    87             if (i & 1)
    88                 sum -= res;
    89             else
    90                 sum += res;
    91         }
    92         printf("%I64d
    ", sum);
    93     }
    94 
    95     return 0;
    96 }
    View Code
  • 相关阅读:
    Python 如何计算当前时间减少或增加一个月
    删除 win8.1中的网络1,网络2,宽带连接1,宽带连接2等网络记录
    Office2003/2010等集成SP的简单方法
    win8.1点击“更改电脑设置”无反应(闪退)
    右键菜单添加带图标的Notepad++
    word2010无法打开文件时的一点对策
    在win7/8/10鼠标右键添加“管理员取得所有权”
    VisualSVNServer 无法启动 could not log pid to file
    半年来经销商云平台工作总结-后端
    半年来经销商云平台工作总结-前端
  • 原文地址:https://www.cnblogs.com/zhaopAC/p/5499693.html
Copyright © 2011-2022 走看看