kuangbin 带你飞 数学基础

模版整理:

晒素数

void init()
{
    cas = 0;
    for (int i = 0 ; i < MAXD ; i++) is_prime[i] = true;
    is_prime[0] = is_prime[1] = false;
    for (int i = 2 ; i < MAXD ; i++)
    {
        if (is_prime[i])
        {
            prime[cas++] = i;
            for (int j = i + i ; j < MAXD ; j += i)
                is_prime[j] = false;
        }
    }
}

合数分解

int x = src[i];
            int cnt = 0,tot = 0;
            for (int j = 0 ; j < cas && prime[j] * prime[j] <= x ; j++)
            {
                if (x % prime[j] == 0)
                {
                    res[cnt++] = prime[j];
                    while (x % prime[j] == 0)
                    {
                        tot++;
                        x /= prime[j];
                    }
                }
            }
            if (x > 1)
            {
                res[cnt++] = x;
                tot++;
            }

大素数筛。1-2^31内某个长度小于10W的区间的素数个数

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 100000;
LL prime[MAXN / 10];
bool is_prime[MAXN + 10];
bool flag[MAXN + 10000] ;
int cas;

void init()
{
    for (int i = 0 ; i < MAXN ; i++) is_prime[i] = true;
    is_prime[0] = false;
    is_prime[1] = false;
    cas = 0;
    for (int i = 2 ; i < MAXN ; i++)
    {
        if (is_prime[i])
        {
            prime[cas++] = i;
            for (int j = i + i ; j < MAXN ; j += i)
                is_prime[j] = false;
        }
    }
}

int main()
{
    init();
    int T,kase = 1;
    scanf("%d",&T);
    while (T--)
    {
        LL a,b;
        scanf("%lld%lld",&a,&b);
        if (b <= 80000)
        {
            int cnt = 0;
            for (int i = a ; i <= b ; i++)
                if (is_prime[i]) cnt++;
            printf("Case %d: %d\n",kase++,cnt);
            continue;
        }
        else
        {
            if (a <= 2) a = 2;
            int sz = b - a;
            for (int i = 0 ; i <= sz ; i++) flag[i] = true;
            for (int i = 0 ; i < cas && prime[i] * prime[i] <= b ; i++)
            {
                int k = a / prime[i];
                if (k * prime[i] < a) k++;
                if (k <= 1) k++;
                while (k * prime[i] <= b)
                {
                    flag[k * prime[i] - a] = false;
                    k++;
                }
            }
            int cnt = 0;
            for (int i = 0 ; i <= sz ; i++)
                if (flag[i] == true) cnt++;
            printf("Case %d: %d\n",kase++,cnt);
        }
    }
    return 0;
}

判断1-N中5的因子的个数,可以将代码5改编

int cnt = 0;
    while (mid)
    {
        cnt += mid / 5;
        mid /= 5;
    }

中国剩余定理

LL china(int n,int *a,int *m)
{
        LL M = 1,d,y,x = 0;
        for (int i = 0 ; i < n ; i++) M *= m[i];
        for (int i = 0 ; i < n ; i++)
        {
                LL w = M / m[i];
                gcd(m[i],w,d,d,y);
                x = (x + y * w * a[i]) % M;
        }
        return (x + M) % M;
}

POJ 1061 青蛙的约会

欧几里德解方程

(y+nt)-(x+mt) = k * L;

(n - m)t + K'L = x - y;

求最小正整数解

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
LL gcd(LL a, LL b) {return a % b == 0 ? b : gcd(b, a % b);}
LL ext_gcd(LL a,LL b,LL &x,LL &y)
{
    if (a == 0 && b == 0) return -1;
    if (b == 0)
    {
        x = 1;
        y = 0;
        return a;
    }
    LL d = ext_gcd(b,a % b,y,x);
    y -= a / b * x;
    return d;
}
LL x,y,m,n,L;

int main()
{
    while (scanf("%I64d%I64d%I64d%I64d%I64d",&x,&y,&m,&n,&L) != EOF)
    {
        LL a = n - m, b = L, c = x - y;
        LL d = gcd(a,b);
        if (c % d != 0)
        {
            puts( "Impossible" );
            continue;
        }
        a /= d;
        b /= d;
        LL x,y;
        ext_gcd(a,b,x,y);
        //cout << a << " " << b << " " << x << " " << y << endl;
        x *= c / d;
        y *= c / d;
        //cout << y << endl;
        //cout << x << endl;
        LL  tmp = L / d;
        x = (x % tmp + tmp) % tmp;
        cout << x << endl;
    }
    return 0;
}
View Code

 

Light Oj 1370 Bi-shoe and Phi-shoe

题意:找到欧拉函数值大于对应数的最小欧拉函数的数

首先素数的欧拉函数值为对应数字减去1

对于任意X,X满足大于等于prime[i],小于等于prime[i + 1],那么这个区间内的所有数字的欧拉函数值都是小于等于

prime[i],那么若想找到欧拉函数大于X的那个值就是大于X的第一个素数

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
/*对任意x,有prime[i]<=x<prime[i+1]必定有EulerPhi[x]<=prime[i],
要满足phi(p)>=x那么p必定为x后面的第一个素数,进行素数打表即可。*/
const int MAXN = 3000010;
bool is_prime[MAXN];
void init()
{
    for (int i = 0 ; i < MAXN ; i++) is_prime[i] = true;
    is_prime[0] = is_prime[1] = false;
    for (int i = 2 ; i < MAXN ; i++)
    {
        if (is_prime[i])
        {
            for (int j = i + i ; j < MAXN ; j += i)
                is_prime[j] = false;
        }
    }
}

int main()
{
    init();
    int T,kase = 1;
    scanf("%d",&T);
    while (T--)
    {
        int n;
        scanf("%d",&n);
        LL sum = 0;
        for (int i = 1 ; i <= n ; i++)
        {
            int x;
            scanf("%d",&x);
            for (int j = x + 1 ; j < MAXN ; j++)
            {
                if (is_prime[j])
                {
                    sum += j;
                    break;
                }
            }
        }
        printf("Case %d: %lld Xukha\n",kase++,sum);
    }
    return 0;
}
View Code

Light Oj 1356 Prime Independence

题意:找到最大的子集使得子集内任何2个数之间都不是素数的倍数的关系

此题可以转换成最大独立集来求,不过好像直接用匈牙利算法会T,所以用HK算法

建图:X部为指数为奇数,Y部为指数为偶数,原音:同奇同偶必然不可能构成一个数是另一个数的素数倍数,

一个为奇数一个为偶数时可以试除一个素数看是否存在然后建图求最大独立集合

另外此题我一开始想简单部分奇部偶部来建图最后除以2.这样可能会T。

LightOj 1341 Aladdin and the Flying Carpet

给出整数 a 和 b ,求区间[b, a] 内的 a 的约数对的个数,a 的约数对(比如[2, 3] 与 [3, 2] 为同一对)。

合数分解后得出(a0 ^ p0) * (a1 ^ p1).....

那么约束对个数为(p0 + 1) * (p1 + 1) * (p2 + 1)......  / 2;

然后从1-B枚举判断A的因子对应减去

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 1000010;
bool is_prime[MAXN];
int cas,prime[MAXN];
LL a,b;

void init()
{
    cas = 0;
    for (int i = 0 ; i < MAXN ; i++) is_prime[i] = true;
    is_prime[0] = is_prime[1] = false;
    for (int i = 2 ; i < MAXN ; i++)
    {
        if (is_prime[i])
        {
            prime[cas++] = i;
            for (int j = i + i ; j < MAXN ; j += i)
                is_prime[j] = false;
        }
    }
}

int tot,cnt;
int num[MAXN],res[MAXN];

int main()
{
    init();
    int T,kase = 1;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%lld%lld",&a,&b);
        if (a <= b * b) 
        {
            printf("Case %d: %d\n",kase++,0);
            continue;
        }
        tot = cnt = 0;
        LL x = a,sum = 1;
        int i = 0;
        while(prime[i] < x && i < cas)
        {
            int val = 0;
            if (x % prime[i] == 0)
            {
                while (x % prime[i] == 0)
                {
                    x /= prime[i];
                    val++;
                }
            }
            sum *= (val + 1);
            i++;
        }
        if (x > 1)
        {
            //res[cnt++] = x;
            sum *= 2;
        }
        //for (int i = 0 ; i < tot ; i++) sum *= (num[i] + 1);
        sum /= 2;
        for (int i = 1 ; i < b ; i++)
            if (a % i == 0) sum--;
        printf("Case %d: %lld\n",kase++,sum);
    }
    return 0;
}
View Code

Light Oj 1336 Sigma Function

定义f(x)为x的所有因子的和,计算H(x)表示从1到X中f(x)为偶数的数字的个数

首先一个数可以表示成(ao ^ p0) * (a1 ^ p1) *......

那么这个数的因子的个数可以表示成(a0 ^ 0 + a0 ^ 1 + ....a0 ^ p0) * (a1 ^ 0 + .... a1 ^ p1) * .....

可见如果为偶数条件很麻烦,如果为奇数那么就是这个所有乘积项全都为奇数

于是问题可以反向来解决,变为统计因子数目为奇数的个数

于是有几个条件第一:如果底数是2,那么这一项构成的乘积项必然是奇数

       第二:如果底数是奇数,那么只有当当前项的次数为偶数的时候该项为奇数

于是判断H(x)我们用二分来判断位置确定答案,对于f(x)为奇数利用DFS操作

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 1000010;
const LL INF = 1e12;
bool is_prime[MAXN];
int cas,prime[MAXN];
LL a,b;

void init()
{
    cas = 0;
    for (int i = 0 ; i < MAXN ; i++) is_prime[i] = true;
    is_prime[0] = is_prime[1] = false;
    for (int i = 2 ; i < MAXN ; i++)
    {
        if (is_prime[i])
        {
            prime[cas++] = i;
            for (int j = i + i ; j < MAXN ; j += i)
                is_prime[j] = false;
        }
    }
}

LL N;
LL val[1800000];
LL num;

void dfs(LL depth,LL sum)
{
    val[num++] = sum;
    if (depth >= cas) return;
    for (LL i = depth ; i < cas ; i++)
    {
        if (i == 0)
        {
            if(sum <= INF / 2) dfs(i,sum * 2LL);
            else return;
        }
        else
        {
            LL res = (LL)prime[i] * (LL)prime[i];
            if (sum <= INF / res) dfs(i,res * sum);
            else return;
        }
    }
}

LL calcu(LL N)
{
    int pos = upper_bound(val,val + num,N)- val;
    return pos;
}

int main()
{
    init();
    num = 0;
    dfs(0,1);
    sort(val,val + num);
    int T,kase = 1;
    scanf("%d",&T);
    while (T--)
    {
        LL N;
        scanf("%lld",&N);
        LL ret = calcu(N);
        printf("Case %d: %lld\n",kase++,N - ret);
    }
    return 0;
}
View Code

Light Oj 1282Leading and Trailing

求N的k次方的前三位和后三位

后三位就是简单的快速幂取模

前三位利用log来处理

N ^ k = 10 ^ T,这里T可以为小数,

可以变成10 ^ x * 10 ^ y;这里X表示整数部分,y表示小数部分,那么含义什么

x表示N^k的数字位数,y表示大小。那么实际上求前三位就是求y。

然后利用POW(10,y)进行相应的运算即可

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const int MOD = 1000;
LL pow_mod(LL val,LL cnt)
{
    LL ret = 1;
    while (cnt)
    {
        if (cnt & 1) ret = ret * val % MOD;
        val = val * val % MOD;
        cnt >>= 1;
    }
    return ret;
}

int main()
{
    int T,kase = 1;
    scanf("%d",&T);
    while (T--)
    {
        LL a,b;
        cin >> a >> b;
        double res = pow(10.0,fmod(b * log10(1.0 * a),1));
        printf("Case %d: %d %03lld\n",kase++,(int)(res * 100.0),pow_mod(a,b));
    }
    return 0;
}
View Code

LightOj 1259 Goldbach`s Conjecture

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 10000010;
bool is_prime[MAXN];
int prime[MAXN / 10],cas;
void init()
{
    cas = 0;
    for (int i = 0 ; i < MAXN ; i++) is_prime[i] = true;
    is_prime[0] = is_prime[1] = false;
    for (int i = 2 ; i < MAXN ; i++)
    {
        if (is_prime[i])
        {
            prime[cas++] = i;
            for (int j = i + i ; j < MAXN ; j += i)
                is_prime[j] = false;
        }
    }
}

int main()
{
    init();
    int T,kase = 1;
    scanf("%d",&T);
    while (T--)
    {
        int n;
        scanf("%d",&n);
        int ret = 0;
        for (int i = 0 ; i < cas && prime[i] <= n / 2 ; i++)
        {
            if (is_prime[n - prime[i]]) ret++;
        }
        printf("Case %d: %d\n",kase++,ret);
    }
    return 0;
}
View Code

LightOj 1245 Harmonic Number (II)

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
LL N;
int main()
{
    int T,kase = 1;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%lld",&N);
        LL ret = 0;
        for (LL i = 1 ; i <= sqrt(1.0 * N) ; i++)
            ret += N / i;
        for (LL i = 1 ; i <= sqrt(1.0 * N) ; i++)
            ret += (N / i - N / (i + 1)) * i;
        if (N / (LL)(sqrt(1.0 * N)) == (LL)sqrt(1.0 * N))
            ret -= (LL)sqrt(1.0 * N);
        printf("Case %d: %lld\n",kase++,ret);
    }
    return 0;
}
View Code

LightOj 1236 Pairs Forming LCM

求N2循环中LCM==N的个数

对于N合数分解有N = a1 ^ p1 * a2 ^ p2 * ....

对于i,j的LCM = N

那么有i = b1 ^ q1 * b2 ^ q2 * ......

   j = c1 ^ x1 * c2 ^ x2  * ......

于是有p1 = max(q1,x1)那么就得到答案了。就是qi,xi的组合方案数,另外注意循环的方式和重复计算

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 10000010;
bool is_prime[MAXN];
int prime[MAXN / 10];
int cas;

void init()
{
    cas = 0;
    for (int i = 0 ; i < MAXN ; i++) is_prime[i] = true;
    is_prime[0] = is_prime[1] = false;
    for (int i = 2 ; i < MAXN ; i++)
    {
        if (is_prime[i])
        {
            prime[cas++] = i;
            for (int j = i + i ; j < MAXN ; j += i)
                is_prime[j] = false;
        }
    }
}

int cnt,tot;
LL N;
int num[MAXN / 10];

int main()
{
    init();
    int T,kase = 1;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%lld",&N);
        LL x = N;
        tot = cnt = 0;
        LL sum = 1;
        for (int i = 0 ; i < cas && prime[i] <= x ; i++)
        {
            if (x % prime[i] == 0)
            {
                tot++;
                int val = 0;
                while (x % prime[i] == 0)
                {
                    val++;
                    x /= prime[i];
                }
                sum *= 2 * val + 1;
            }
        }
        if (x > 1)
        {
            sum *= 3;
            tot++;
        }
        sum = sum / 2 + 1;
        printf("Case %d: %lld\n",kase++,sum);
    }
    return 0;
}
View Code

LightOj 1234 Harmonic Number

计算1/1 + 1/2 + 1/3 + 1/4 + .......

这个题有三种处理方法

第一种如果直接开对应数组是开不下的,但是时间上是够的,于是可以适当优化空间,

所遇预先没50个存一组剩下的不满足50一组的直接暴力

 

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 1e8;
double ans[MAXN / 50 + 10];

void init()
{
    ans[0] = 0.0;
    double cur = 0.0;
    for (int i = 1 ; i <= MAXN ; i++)
    {
        cur += 1.0 / (double)i;
        if (i % 50 == 0) ans[i / 50] = cur;
    }
}

int main()
{
    init();
    int T,kase = 1;
    scanf("%d",&T);
    while (T--)
    {
        int N;
        scanf("%d",&N);
        int st = N / 50;
        double ret = ans[st];
        for (int i = st * 50 + 1 ; i <= N ; i++)
            ret += 1.0 / (double)i;
        printf("Case %d: %.10lf\n",kase++,ret);
    }
    return 0;
}
View Code

第二种是离线处理这个很好。

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const double eps = 1e-9;
const int MAXN = 10010;
struct node
{
    int idx,ask;
    double ans;
    friend bool operator < (const node &a,const node &b)
    {
        return a.ask < b.ask;
    }
}src[MAXN];

int cmp(const node&a,const node &b)
{
    return a.idx < b.idx;
}

int main()
{
    int T,kase = 1;
    scanf("%d",&T);
    for (int i = 1 ; i <= T ; i++) scanf("%d",&src[i].ask);
    for (int i = 1 ; i <= T ; i++) src[i].idx = i;
    sort(src + 1,src + 1 + T);
    double cur = 0.0;
    int step = 1;
    for (int i = 1 ; i <= 1e8 ; i++)
    {
        if (step > T) break;
        cur = cur + 1.0 / (double)i;
        while (src[step].ask == i)
        {
            src[step].ans = cur;
            step++;
        }
    }
    sort(src + 1,src + 1 + T ,cmp);
    for (int i = 1 ; i <= T ; i++)
    {
        printf("Case %d: %.10lf\n",kase++,src[i].ans + eps);
    }
    return 0;
}
View Code

第三个是神奇的数学结论

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 1000010;
double ret[MAXN];
#define gamma 0.57721566490153286060651209008240243104215933593992
int N;

int main()
{
    ret[0] = 0.0;
    for (int i = 1 ; i < MAXN ; i++) ret[i] = ret[i - 1] + 1.0 / (double)i;
    int T,kase = 1;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d",&N);
        printf("Case %d: ",kase++);
        if (N < MAXN) printf("%.10lf\n",ret[N]);
        else
        {
            printf("%.10lf\n",(log(N) + log(N + 1)) / 2 + gamma);
        }
    }
    return 0;
}
View Code

LightOj 1220 Mysterious Bacteria

求一个数最多是一个数的几次幂

合数分解次数求GCD

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 1000010;
const int INF = 0x3f3f3f3f;
bool is_prime[MAXN];
int cas,prime[MAXN];

void init()
{
    cas = 0;
    for (int i = 0 ; i < MAXN ; i++) is_prime[i] = true;
    is_prime[0] = is_prime[1] = false;
    for (int i = 2 ; i < MAXN ; i++)
    {
        if (is_prime[i])
        {
            prime[cas++] = i;
            for (int j = i + i ; j < MAXN ; j += i)
                is_prime[j] = false;
        }
    }
}

int main()
{
    init();
    int T,kase = 1;
    scanf("%d",&T);
    while (T--)
    {
        int val = 0;
        LL N;
        scanf("%lld",&N);
        LL x = N;
        if (x < 0LL) x = -x;
        for (int i = 0 ; i < cas && prime[i] <= x ; i++)
        {
            int cnt = 0;
            if (x % prime[i] == 0)
            {
                while (x % prime[i] == 0)
                {
                    cnt++;
                    x /= prime[i];
                }
                val = gcd(val,cnt);
            }
        }
        if (x > 1)
        {
            val = 1;
        }
        if (N < 0)
        {
            while (val % 2 == 0) val /= 2;
        }
        printf("Case %d: %d\n",kase++,val);
    }
    return 0;
}
View Code

LightOj 1214 Large Division

判断大数是不是能整除。一个是直接JAVA水,另一个利用同余定理做

JAVA:

import java.util.*;
import java.math.BigInteger;
import java.util.Scanner;

public class Main
{
    public static void main(String args[])
    {
        Scanner sc = new Scanner(System.in);
        BigInteger a,b,d;
        int T;
        T = sc.nextInt();
        int kase = 1;
        while (T-- != 0)
        {
            a = new BigInteger(sc.next());
            b = new BigInteger(sc.next());
            a = a.abs();
            b = b.abs();
            if (a.mod(b).equals(BigInteger.ZERO))
            {
                System.out.println("Case " + kase++ + ": divisible");
            }
            else
            {
                System.out.println("Case " + kase++ + ": not divisible");
            }
        }
    }
}
View Code
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 10010;
char str[MAXN];
LL m;

int main()
{
    int T,kase = 1;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%s%lld",str,&m);
        LL cur = 0;
        int len = strlen(str);
        for (int i = 0 ; i < len ; i++)
        {
            if (str[i] == '-') continue;
            cur = (cur * 10 + str[i] - '0') % m;
        }
        if (cur == 0) printf("Case %d: divisible\n",kase++);
        else printf("Case %d: not divisible\n",kase++);
    }
    return 0;
}
View Code

LightOj 1213 Fantasy of a Summation

利用简单的方法计算相应的代码

感觉这个题有点期望的意思

一共有N^K中组合,每种组合K个数字,平均分给N个数字,然后一直乘到一起

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 1010;
LL sum;
LL N,K,MOD;
LL src[MAXN];

LL pow_mod(LL x,int cnt)
{
    LL ret = 1;
    while (cnt)
    {
        if (cnt & 1) ret = ret * x % MOD;
        x = x * x % MOD;
        cnt >>= 1;
    }
    return ret;
}


int main()
{
    int T,kase = 1;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%lld%lld%lld",&N,&K,&MOD);
        for (int i = 1 ; i <= N ; i++)
            scanf("%lld",&src[i]);
        LL ret = 0;
        for (int i = 1 ; i <= N ; i++)
        {
            ret = (ret + src[i]) % MOD;
        }
        LL val = pow_mod(N,K - 1);
        printf("Case %d: %lld\n",kase++,ret * val % MOD * K % MOD);
    }
    return 0;
}
View Code

LightOj 1197 Help Hanzo

区间内素数的个数,大区间的。区间长度很少

大区间筛小区间的题目

利用预先筛根号N的素数然后做就行了。这个是个模版类的问题

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 100000;
LL prime[MAXN / 10];
bool is_prime[MAXN + 10];
bool flag[MAXN + 10000] ;
int cas;

void init()
{
    for (int i = 0 ; i < MAXN ; i++) is_prime[i] = true;
    is_prime[0] = false;
    is_prime[1] = false;
    cas = 0;
    for (int i = 2 ; i < MAXN ; i++)
    {
        if (is_prime[i])
        {
            prime[cas++] = i;
            for (int j = i + i ; j < MAXN ; j += i)
                is_prime[j] = false;
        }
    }
}

int main()
{
    init();
    int T,kase = 1;
    scanf("%d",&T);
    while (T--)
    {
        LL a,b;
        scanf("%lld%lld",&a,&b);
        if (b <= 80000)
        {
            int cnt = 0;
            for (int i = a ; i <= b ; i++)
                if (is_prime[i]) cnt++;
            printf("Case %d: %d\n",kase++,cnt);
            continue;
        }
        else
        {
            if (a <= 2) a = 2;
            int sz = b - a;
            for (int i = 0 ; i <= sz ; i++) flag[i] = true;
            for (int i = 0 ; i < cas && prime[i] * prime[i] <= b ; i++)
            {
                int k = a / prime[i];
                if (k * prime[i] < a) k++;
                if (k <= 1) k++;
                while (k * prime[i] <= b)
                {
                    flag[k * prime[i] - a] = false;
                    k++;
                }
            }
            int cnt = 0;
            for (int i = 0 ; i <= sz ; i++)
                if (flag[i] == true) cnt++;
            printf("Case %d: %d\n",kase++,cnt);
        }
    }
    return 0;
}
View Code

LightOj 1138 Trailing Zeroes (III)

最小的数阶乘末尾的0的个数

每个因子2*5可以出个末尾0,那么有从小到大的过程中,2的数量绝对够多,于是变成了从1到N中5的因子的个数

另外为了优化需要套上一个二分代码。

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
LL Q;
const LL INF = 0x3f3f3f3f;

bool judge(LL mid)
{
    int cnt = 0;
    while (mid)
    {
        cnt += mid / 5;
        mid /= 5;
    }
    return cnt >= Q;
}

int main()
{
    int T,kase = 1;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%lld",&Q);
        LL L = 0 ,R = INF;
        LL ans = -1;
        while (L <= R)
        {
            LL mid = (L + R) / 2;
            if (judge(mid))
            {
                R = mid - 1;
                ans = mid;
            }
            else L = mid + 1;
        }
        bool flag = true;
        LL tmp = ans;
        LL val = 0;
        while (tmp)
        {
            val += tmp / 5;
            tmp /= 5;
        }
        if (val != Q) flag = false;
        if (flag)   printf("Case %d: %lld\n",kase++,ans);
        else printf("Case %d: impossible\n",kase++);
    }
    return 0;
}
View Code

接下来是几个大白的题目

Uva 11426 GCD - Extreme (II)

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
const int MAXN = 4000000;
int phi[MAXN + 10];
LL ret[MAXN + 10];

void init()
{
    memset(ret,0,sizeof(ret));
    for(int i = 1 ; i <= MAXN ; i++) phi[i] = i;
    for(int i = 2 ; i <= MAXN; i ++)
    {
        if(phi[i] == i)
        {
            for(int j = i ; j <= MAXN ; j += i)
                phi[j] = phi[j] / i * (i - 1);
        }
        for(int j = 1; j * i <= MAXN ; j ++)
            ret[j * i] += j * phi[i];
    }
    for (int i = 1 ; i <= MAXN ; i++) ret[i] += ret[i - 1];
}

int main()
{
    init();
    int N;
    while (scanf("%d",&N) != EOF) if (N == 0) break;
        else printf("%lld\n",ret[N]);
    return 0;
}
View Code

UVA 11754 Codefeat

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
void gcd(LL a,LL b,LL &d,LL &x,LL &y)
{
        if (b == 0) {d = a; x = 1; y = 0;}
        else  {gcd(b,a % b,d,y,x); y -= x * (a / b);}
}
LL china(int n,int *a,int *m)
{
        LL M = 1,d,y,x = 0;
        for (int i = 0 ; i < n ; i++) M *= m[i];
        for (int i = 0 ; i < n ; i++)
        {
                LL w = M / m[i];
                gcd(m[i],w,d,d,y);
                x = (x + y * w * a[i]) % M;
        }
        return (x + M) % M;
}
const int MAXC = 9;
const int MAXK = 100;
const int LIMIT = 10000;
set<int>value[MAXC];
int C,X[MAXC],K[MAXC];
int Y[MAXC][MAXK];
void slove_enum(int S,int bc)
{
        for (int  c = 0 ; c < C; c++) if (c != bc)
        {
                value[c].clear();
                for (int i = 0 ; i < K[c] ; i++)  value[c].insert(Y[c][i]);
        }
        for (int t = 0 ; S != 0 ; t++)
        {
                for (int i = 0 ; i < K[bc] ; i++)
                {
                        LL n = (LL)X[bc] * t + Y[bc][i];
                        if (n == 0) continue;
                        bool flag = true;
                        for (int c = 0 ; c < C; c++)
                        {
                                if (c != bc)
                                {
                                        if (value[c].count(n % X[c]) == 0) {flag = false; break;}
                                }
                        }
                        if (flag) { printf("%lld\n",n); if (--S == 0) break;}
                }
        }
}
int a[MAXC];
vector<LL>sol;
void dfs(int depth)
{
        if (depth == C) sol.push_back(china(C,a,X));
        else for (int i = 0 ; i < K[depth]; i++)
        {
                a[depth] = Y[depth][i];
                dfs(depth + 1);
        }
}
void slove_china(int S)
{
        sol.clear();
        dfs(0);
        sort(sol.begin(),sol.end());
        LL M = 1;
        for (int i = 0 ; i < C; i++) M *= X[i];
        vector<LL>ans;
        for (int i = 0; S != 0 ; i++)
        {
                for (int j = 0 ; j < (int)sol.size(); j++)
                {
                        LL n = M * i + sol[j];
                        if (n > 0)
                        {
                                printf("%lld\n",n);
                                if (--S == 0) break;
                        }
                }
        }
}
int main()
{
        int S;
        while (scanf("%d%d",&C,&S) != EOF)
        {
                if (C == 0) break;
                LL tot = 1;
                int best = 0;
                for (int c = 0 ; c < C ; c++)
                {
                        scanf("%d%d",&X[c],&K[c]);
                        tot *= K[c];
                        for (int i = 0 ; i < K[c]; i++) scanf("%d",&Y[c][i]);
                        sort(Y[c],Y[c] + K[c]);
                        if (K[c] * X[best] < K[best] * X[c]) best = c;
                }
                if (tot > LIMIT) slove_enum(S,best);
                else slove_china(S);
                printf("\n");
        }
        return 0;
}
View Code

UVA 11916 Emoogle Grid

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
LL N,K,B,R;
const LL MOD = 100000007;
const int MAXN = 1010;
int x[MAXN],y[MAXN];
LL M;
set<pair<int,int> >s;

LL pow_mod(LL x,int cnt)
{
    LL ret = 1;
    while (cnt)
    {
        if (cnt & 1) ret = ret * x % MOD;
        x = x * x % MOD;
        cnt >>= 1;
    }
    return ret;
}

void ext_gcd(LL a,LL b,LL &d,LL &x,LL &y)
{
    if (b == 0) {d = a; x = 1 ; y = 0;}
    else {ext_gcd(b,a % b,d,y,x); y -= x * (a / b);}
}

LL inv(LL a,LL n)
{
    LL d,x,y;
    ext_gcd(a,n,d,x,y);
    return d == 1 ? (x + n) % n : -1;
}

LL log_mod(LL a,LL b,LL n)
{
    LL m,v,e = 1;
    m = (LL)sqrt(n + 0.5);
    v = inv(pow_mod(a,m),n);
    map<LL,LL>x;
    x[1] = 0;
    for (int i = 1 ; i < m ; i++)
    {
        e = e * a % m;
        if (!x.count(e)) x[e] = (LL)i;
    }
    for (int i = 0 ; i < m ; i++)
    {
        if (x.count(b)) return (LL)i * m + x[b];
        b = b * v % n;
    }
    return -1;
}

LL getnum()
{
    int tot = 0;
    for (int i = 1 ; i <= B ; i++)
    {
        if (x[i] != M && !s.count(make_pair(x[i] + 1,y[i]))) tot++;
    }
    tot += N;
    for (int i = 1 ; i <= B ; i++) if (x[i] == 1) tot--;
    return (pow_mod(K,tot) * pow_mod(K - 1,(M * N  - tot - B))) % MOD;
}

LL calcu()
{
    LL cnt = getnum();
    printf("%d\n",cnt);
    if (cnt == R) return M;
    int num = 0;
    for (int i = 1 ; i <= B ; i++) if (x[i] == M) num++;
    cnt = (cnt * pow_mod(K,num)) % MOD;
    cnt = (cnt * pow_mod(K - 1,N - num)) % MOD;
    if (cnt == R)return M + 1;
    //printf("%lld %lld\n",pow_mod(K - 1,N),pow_mod(K - 1,N));
    return log_mod(pow_mod(K - 1,N),R * pow_mod(K - 1,N),MOD) + M + 1;
}
int main()
{
    int T,kase = 1;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%lld%lld%lld%lld",&N,&K,&B,&R);
        R %= MOD;
        s.clear();
        M = 1;
        for (int i = 1 ; i <= B ; i++)
        {
            scanf("%d%d",&x[i],&y[i]);
            M = max(M,(LL)x[i]);
            s.insert(make_pair(x[i],y[i]));
        }
        printf("Case %d: %lld\n",kase++,calcu());
    }
    return 0;
}
View Code

 

POJ 2115 同青蛙的约会

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
LL gcd(LL a, LL b) {return a % b == 0 ? b : gcd(b, a % b);}
LL ext_gcd(LL a,LL b,LL &x,LL &y)
{
    if (a == 0 && b == 0) return -1;
    if (b == 0)
    {
        x = 1;
        y = 0;
        return a;
    }
    LL d = ext_gcd(b,a % b,y,x);
    y -= a / b * x;
    return d;
}
LL A,B,C,K;

int main()
{
    while (scanf("%I64d%I64d%I64d%I64d",&A,&B,&C,&K) != EOF)
    {
        if (A == 0 && B == 0 && C == 0 && K == 0) break;
        LL a = C, b = (1LL << K), c = B - A;
        LL d = gcd(a,b);
        if (c % d != 0)
        {
            puts( "FOREVER" );
            continue;
        }
        a /= d;
        b /= d;
        LL x,y;
        ext_gcd(a,b,x,y);
        //cout << a << " " << b << " " << x << " " << y << endl;
        x *= c / d;
        y *= c / d;
        //cout << y << endl;
        //cout << x << endl;
        LL  tmp = (1LL << K) / d;
        x = (x % tmp + tmp) % tmp;
        printf("%I64d\n",x);
    }
    return 0;
}
View Code

HDU 2161 Prime太水了。

UVA 11827 太水了

UVA 10200 太水了

SGU 106 The equation

判断欧几里德可行解在固定区间内的个数

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
LL gcd(LL a, LL b) {return a % b == 0 ? b : gcd(b, a % b);}
LL a,b,c,x1,x2,yy1,y2;
LL x0,yy0;
LL ext_gcd(LL a,LL b,LL &x,LL &y)
{
    if (a == 0 && b == 0) return -1;
    if (b == 0)
    {
        x = 1;
        y = 0;
        return a;
    }
    LL d = ext_gcd(b,a % b,y,x);
    y -= a / b * x;
    return d;
}

int main()
{
    while (scanf("%I64d%I64d%I64d%I64d%I64d%I64d%I64d",&a,&b,&c,&x1,&x2,&yy1,&y2) != EOF)
    {
        c = -c;
        if (c < 0)
        {
            a = -a;
            b = -b;
            c = -c;
        }
        if (a < 0)
        {
            a = -a;
            LL tmp = -x1;
            x1 = -x2;
            x2 = tmp;
        }
        if (b < 0)
        {
            b = -b;
            LL tmp = -yy1;
            yy1 = - y2;
            y2 = tmp;
        }
        if (a == 0 && b == 0)
        {
            if (c == 0)
            {
                printf("%I64d\n",(x2 - x1 + 1) * (y2 - yy1 + 1));
            }
            printf("%d\n",0);
            continue;
        }
        else if (a == 0)
        {
            if (c % b == 0)
            {
                if (c / b >= yy1 && c / b <= y2)
                {
                    printf("%I64d\n",x2 - x1 + 1);
                }
                else printf("%d\n",0);
            }
            continue;
        }
        else if (b == 0)
        {
            if (c % a == 0)
            {
                if (c / a >= x1 && c / a <= x2)
                {
                    printf("%I64d\n",y2 - yy1 + 1);
                }
                printf("%d\n",0);
            }
            continue;
        }
        LL d = gcd(a,b);
        if (c % d != 0)
        {
            puts("0");
            continue;
        }
        a = a / d;
        b = b / d;
        c = c / d;
        ext_gcd(a,b,x0,yy0);
        x0 *= c;
        yy0 *= c;
       // printf("%I64d %I64d %I64d %I64d %I64d\n",a,b,c,x0,yy0);
        LL l1 = (LL)ceil((double)(x1 - x0) / (double)(b));
        LL l2 = (LL)ceil((double)(yy0 - y2) / (double)(a));
        LL r1 = (LL)floor((double)(x2 - x0) / (double)(b));
        LL r2 = (LL)floor((double)(yy0 - yy1) / (double)(a));
       // cout << l1 << " " << r1 << endl;
       // cout << l2 << " " << r2 << endl;
        LL l = max(l1,l2);
        LL r = min(r1,r2);
        if (l > r) puts("0");
        else printf("%I64d\n",r - l + 1LL);
    }
    return 0;
}
View Code

POJ 2478 直接欧拉前N想和。

UVA 11752 The Super Powers

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL unsigned long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);}
set<LL>ans;
set<LL>::iterator it;
bool is_prime[110];

void init()
{
    for (int i = 0 ; i < 110 ; i++) is_prime[i] = true;
    is_prime[0] = is_prime[1] = true;
    for (int i = 2 ; i < 110 ; i++)
    {
        if (is_prime[i])
        {
            for (int j = i + i ; j < 110 ; j += i)
                is_prime[j] =  false;
        }
    }
}

int main()
{
    init();
    ans.clear();
    ans.insert(1);
    for (LL i = 2 ; i < (1 << 16) ; i++)
    {
        LL limit = (LL)ceil(64.0 * log10(2.0) / log10(i));
        //cout << i << " " << limit << endl;
       // scanf("%*d");
        LL cur = 1;
        for (int j = 1 ; j < limit ; j++)
        {
            cur *= i;
            if (is_prime[j] == false)
            {
                ans.insert(cur);
               // cout << cur << endl;
               // scanf("%*d");
            }
        }
    }
    int cnt = 0;
    for (it = ans.begin() ; it != ans.end() ; it++)
     cout << *it << endl;
    return 0;
}
View Code

 

posted @ 2015-12-09 22:38  Commence  阅读(410)  评论(0编辑  收藏  举报