暑假集训 || 初等数论

·中国剩余定理

 

·扩展中国剩余定理

 

·莫比乌斯反演

模板:

void Moblus()
{
    memset(check,false,sizeof(check));
    mu[1] = 1;
    int tot = 0;
    for(int i = 2; i <= MMX; i++)
    {
        if( !check[i] )
        {
            prime[tot++] = i;
            mu[i] = -1;
        }
        for(int j = 0; j < tot; j++)
        {
            if(i * prime[j] > MMX) break;
            check[i * prime[j]] = true;
            if( i % prime[j] == 0)
            {
                mu[i * prime[j]] = 0;
                break;
            }
            else
            {
                mu[i * prime[j]] = -mu[i];
            }
        }
    }
}
View Code

 HDU 1695

题意:给abcd,a==1, c==1, 求[a, b]中的x 和[c, d]中的y, 是的gcd(x, y) == k,问有多少对这样的x和y,(5, 3)和(3, 5)算一对

思路:https://blog.csdn.net/lixuepeng_001/article/details/50577932 这里讲的比较详细。。好难QAQ

注意k可能为0,为0的时候时候也要输出case

然后乘的时候会爆int,不如全改成LL哇

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const LL SZ = 100100;
bool check[SZ];
LL mu[SZ], prime[SZ];
void Moblus()
{
    memset(check,false,sizeof(check));
    mu[1] = 1;
    LL tot = 0;
    for(LL i = 2; i <= 100050; i++)
    {
        if(!check[i])
        {
            prime[tot++] = i;
            mu[i] = -1;
        }
        for(LL j = 0; j < tot; j++)
        {
            if(i * prime[j] > 100050) break;
            check[i * prime[j]] = true;
            if( i % prime[j] == 0)
            {
                mu[i * prime[j]] = 0;
                break;
            }
            else
            {
                mu[i * prime[j]] = -mu[i];
            }
        }
    }
}
int main()
{
    int T, tt = 0;
    scanf("%d", &T);
    Moblus();
    while(T--)
    {
        LL a, b, c, d, k;
        scanf("%lld %lld %lld %lld %lld", &a, &b, &c, &d, &k);
        if(k == 0)
        {
            printf("Case %d: 0\n", ++tt);
            continue;
        }
        b /= k, d /= k;
        if(b > d) swap(b, d);//b <= d
        LL ans = 0, add = 0;
        for(LL i = 1; i <= b; i++)
            ans += (b / i) * (d / i) * mu[i]);
        for(LL i = 1; i <= b; i++)
            add += (b / i) * (b / i) * mu[i]);
        printf("Case %d: %lld\n", ++tt, ans - add/2);
    }
    return 0;
}
View Code

 

 

·法雷级数

就是这个东东

中间每一个数的分子都是它左右两数分子之和,分母也是

用途:分数逼近,类似二分

HDU 6290

题意:给一个无理数,求出分母在1e5以内的最接近它的最简分数

思路:法雷级数里面能表示所有最简的真分数,用类似二分的方法不断逼近,取两个数中间的分数看要求的无理数在它的左边还是右边

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef long double LD;
const int SZ = 1000100;
const int eps = 1e-9;
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int k;
        scanf("%d", &k);
        LD dk = pow((LD)k, (LD)2.0/3.0);
        LL tmp = floor(dk);
        dk -= tmp;
        LL a1 = 0, a2 = 1, b1 = 1, b2 = 1;
        while(b1+b2 <= 100000LL)
        {
            LL mida = a1+a2, midb = b1+b2;
            LD ans = (LD)mida / midb;
            if(ans < dk) a1 = mida, b1 = midb;
            else a2 = mida, b2 = midb;
        }
        LD ans1 = (LD)a1 / b1, ans2 = (LD)a2 / b2;
        if(dk - ans1 < ans2 - dk) printf("%lld/%lld\n", a1 + tmp * b1, b1);
        else printf("%lld/%lld\n", a2 + tmp * b2, b2);
    }
    return 0;
}
View Code

 

 

·指数循环节

 

·Lucas定理

 

·BM算法

posted @ 2018-08-27 22:26  舒羽倾  阅读(170)  评论(0编辑  收藏  举报