数论 2017.1.14

1、HDU 5750 Dertouzos

官方题解:


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;

const ull mod = 1e9 + 7;
const int INF = 0x7fffffff;
const int maxn = 7e4;
int n, d;
bool vis[maxn];
int Prime[maxn];
int P_num = 0;
int mp[maxn];

void Init(void);
int Get_Mp(int x);

int main()
{
#ifdef __AiR_H
    freopen("in.txt", "r", stdin);
#endif // __AiR_H
    int T;
    scanf("%d", &T);
    Init();
    while (T--) {
        scanf("%d%d", &n, &d);
        if (n-1 > d) {
            if (d >= maxn) {
                int t = (n-1)/d;
                int pos = -1;
                for (int i = 0; Prime[i] <= t; ++i) {
                    if (d%Prime[i] == 0) {
                        pos = i;
                        break;
                    }
                }
                int num = 0;
                if (pos == -1) {
                    num = upper_bound(Prime, Prime+P_num, t) - Prime;
                } else {
                    num = pos+1;
                }
                printf("%d\n", num);
            } else {
                int Min = min(mp[d], (n-1)/d);
                int num = upper_bound(Prime, Prime+P_num, Min) - Prime;
                printf("%d\n", num);
            }
        } else {
            printf("0\n");
        }
    }
    return 0;
}

void Init(void)
{
    memset(vis, false, sizeof(vis));
    memset(mp, -1, sizeof(mp));
    for (int i = 2; i < maxn; ++i) {
        if (!vis[i]) {
            vis[i] = true;
            Prime[P_num++] = i;
            mp[i] = i;
            int j = i*2;
            while (j < maxn) {
                if (mp[j] == -1) {
                    mp[j] = i;
                }
                vis[j] = true;
                j += i;
            }
        }
    }
}


2、POJ 1426 Find The Multiple

参考:http://blog.csdn.net/lyy289065406/article/details/6647917
同余模定理
(a*b)%n = (a%n * b%n)% n

(a+b)%n = (a%n + b%n)% n

前一步 (11*10+1)%6=2   即k=110 , k%6=2
当前步 (110*10+1)%6=2
由同余模定理  (110*10+1)%6 = ((110*10)%6+1%6 )%6 = ((110%6 * 10%6)%6 +1 )%6
不难发现下划线部分110%6等于 (11*10+0)%6 = 2
所以当前步(110*10+1)%6可以转变为  (2*10+1)%6=2
很显然地,这种处理把k=110 等价于 k=2
即用 前一步操作得到的余数 代替 当前步的k值
而n在200的范围内, 余数值不可能超过3位数, 这就解决了大数的问题
n=6时,求余操作进行了14次,对应地,bfs时*10的操作也进行了14次
令i=14,通过观察发现,i%2恰好就是 6 的倍数的最低位数字
i/2  再令 i%2 ,恰好就是 6 的倍数的次低位数字
循环这个操作,直到i=0,就能得到 6的 01倍数(一个01队列),倒序输出就是所求
这样就完成了 *10 操作到 %2 操作的过渡

#include <iostream>
#include <cstdio>
#include <queue>

using namespace std;

const int maxn = 1e6;
int n;
int mod[maxn];

int main()
{
//    freopen("in.txt", "r", stdin);
    while (scanf("%d", &n) != EOF && n != 0) {
        mod[1] = 1%n;
        int Count = 2;
        while (mod[Count-1] != 0) {
            mod[Count] = (mod[Count/2]*10 + Count%2) % n;
            ++Count;
        }
        --Count;
        int num = 0;
        while (Count) {
            mod[num] = Count%2;
            ++num;
            Count >>= 1;
        }
        while (num) {
            --num;
            printf("%d", mod[num]);
        }
        printf("\n");
    }
    return 0;
}


3、HDU 5793 A Boring Question

solution by uestc

这个推导看不太懂,我当时是暴力打表找的规律

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>
#include <bitset>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;

const ull mod = 1e9 + 7;
const int INF = 0x7fffffff;
int n, m;

ull Pow(ull x, ull n);

int main()
{
#ifdef __AiR_H
    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
#endif // __AiR_H
    int T;
    scanf("%d", &T);
    while (T--) {
        scanf("%d%d", &n, &m);
        ull ans = ((Pow(m, n+1) - 1) * Pow(m-1, mod-2)) % mod;
        printf("%I64d\n", ans);
    }
    return 0;
}

ull Pow(ull x, ull n)
{
    ull ret = 1;
    ull t = x % mod;
    while (n) {
        if (n & 1) {
            ret *= t;
            ret %= mod;
        }
        n >>= 1;
        t = (t*t) % mod;
    }
    return ret;
}

4、POJ 2649 Factovisors

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
#include <stack>
#include <set>
#include <bitset>
#include <ctime>
#include <cctype>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> Pair;

const int mod = 1e9 + 7;
const int INF = 0x7fffffff;
const int maxn = 7e4 + 10;

int prime_cnt = 0;
int n, m;
map<int, int> Map;
int prime[maxn];
bool vis[maxn];

int cnt(int x, int y);
void Init(void);

int main()
{
#ifdef __AiR
    freopen("in.txt", "r", stdin);
#endif // __AiR_H_
    Init();
    while (scanf("%d %d", &n, &m) != EOF) {
        if (n == 0 && m == 1) {
            printf("%d divides %d!\n", m, n);
            continue;
        }
        if (m == 0) {
            printf("%d does not divide %d!\n", m, n);
            continue;
        }
        Map.clear();
        if (n >= m) {
            printf("%d divides %d!\n", m, n);
        } else {
            int m_t = m;
            for (int i = 0; i < prime_cnt; ++i) {
                while (m_t % prime[i] == 0) {
                    ++Map[prime[i]];
                    m_t /= prime[i];
                }
                if (m_t == 1) {
                    break;
                }
            }
            if (m_t != 1) {
                Map[m_t] = 1;
            }
            bool flag = true;
            map<int, int>::iterator itr;
            for (itr = Map.begin(); itr != Map.end(); ++itr) {
                int a = itr->first, b = itr->second;
                if (cnt(n, a) < b) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                printf("%d divides %d!\n", m, n);
            } else {
                printf("%d does not divide %d!\n", m, n);
            }
        }
    }
    return 0;
}

int cnt(int x, int y)
{
    int ret = 0;
    int t = x / y;
    while (t) {
        ret += t;
        t /= y;
    }
    return ret;
}

void Init(void)
{
    memset(vis, false, sizeof(vis));
    for (int i = 2; i < maxn; ++i) {
        if (!vis[i]) {
            vis[i] = true;
            prime[prime_cnt++] = i;
            int j = i * 2;
            while (j < maxn) {
                vis[j] = true;
                j += i;
            }
        }
    }
}

5、CSU 1755 阶数

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <cmath>
#include <cctype>
#include <ctime>

using namespace std;

#define REP(i, n) for (int i = 0; i < (n); ++i)

typedef long long ll;
typedef pair<int, int> Pair;

const int INF = 0x7fffffff;
const int maxn = 4e4;
int prime[maxn], divisor[maxn];
bool vis[maxn];
int prime_cnt = 0, divisor_cnt = 0, mod;

void init(void);
int euler(int x);
int degree(int a, int phi);
int my_pow(int x, int n);

int main() {
#ifdef __AiR_H
    freopen("in.txt", "r", stdin);
#endif // __AiR_H
    int k, a, n;
    init();
    scanf("%d", &k);
    while (k--) {
        scanf("%d %d", &a, &n);
        mod = n; divisor_cnt = 0;
        if (__gcd(a, n) != 1) { printf("-1\n"); continue; }
        printf("%d\n", degree(a, euler(n)));
    }
#ifdef __AiR_H
    printf("Time used = %.2fs\n", (double)clock() / CLOCKS_PER_SEC);
#endif // __AiR_H
    return 0;
}

int degree(int a, int phi) {
    for (int i = 1; i * i <= phi; ++i) {
        if (phi % i == 0) {
            if (phi / i == i) {
                divisor[divisor_cnt++] = i;
            } else {
                divisor[divisor_cnt++] = i;
                divisor[divisor_cnt++] = phi / i;
            }
        }
    }
    sort(divisor, divisor + divisor_cnt);
    int ret = 0;
    REP(i, divisor_cnt) {
        if (my_pow(a, divisor[i]) == 1) { ret = divisor[i]; break; }
    }
    return ret;
}

int my_pow(int x, int n) {
    ll ret = 1, t = x % mod;
    while (n) {
        if (n & 1) { ret *= t; ret %= mod; }
        n >>= 1; t *= t; t %= mod;
    }
    return (int)ret;
}

void init(void) {
    memset(vis, false, sizeof(vis));
    for (int i = 2; i < maxn; ++i) {
        if (!vis[i]) {
            prime[prime_cnt++] = i;
            for (int j = i; j < maxn; j += i) { vis[j] = true; }
        }
    }
}

int euler(int x) {
    int ret = x;
    for (int i = 0; prime[i] * prime[i] <= x; ++i) {
        if (x % prime[i] == 0) {
            ret = ret / prime[i] * (prime[i] - 1); x /= prime[i];
            while (x % prime[i] == 0) { x /= prime[i]; }
        }
    }
    if (x != 1) { ret = ret / x * (x - 1); }
    return ret;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值