sduacm16级寒假训练 素筛 快速幂 GCD

POJ 2739 Sum of Consecutive Prime Numbers

#include<cstdio>
#include<iostream>
using namespace std;
const int maxnp = 10000;
bool isp[maxnp];
int prime[50000], ans[10000 + 5];
int num = 0;
void xs()
{
    for(int i = 2; i <= maxnp; i++)
    {
        if (!isp[i])
            prime[num++] = i;
        for(int j = 0; j <= num && i * prime[j] <= maxnp; j++)
        {
            isp[i * prime[j]] = true;
            if (i % prime[j] == 0)
                 break;
        }
    }
}
int main()
{
    xs();
    ans[2] = 1;
    for(int i = 3; i <= 10000; i++)
    {
        int l = 0, r = 0, sum = 2;
        for(int j = 1; j < num; j++)
        {
            if(prime[j] > i)
                break;
            sum += prime[j];
            while (sum > i)
            {
                sum -= prime[l];
                l++;
            }
            if (sum == i)
                ans[i]++;
        }
    }
    int n;
    scanf("%d", &n);
    while (n)
    {
        printf("%d\n", ans[n]);
        scanf("%d", &n);
    }
    return 0;
}

POJ 2689 Prime Distance(大区间素数筛选)

[吐槽]

坚决要吐槽这道题。。。。md,wa了好多发,找了好长时间的错…..(好吧。。。证明我太弱),弱弱地说一

句,筛选长度(<10^6)的素数,我们知道,n最小的质因子a肯定小于根号n(如果a大于根号n,那么与它

对应的因子b肯定小于根n,如果b是素数,那么与a为最小质因子矛盾,如果b为合数,那么肯定能拆成更小

的素数),所以我们把50000内的素数筛出来,然后用这些数去筛掉区间的合数就可以……………………………..

此外,遇到这种在int数据范围极限的数,不要吝啬了,一定要开longlong,不然我打个for循环都崩了……..

还检查好长时间才检查出来

PS:自己制造数据的时候应该有意识地造几个极限数据(也包括极限小那种)

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int maxnp = 50000;
bool isp[maxnp + 5];
int prime[50000 + 5], ans[10000 + 5], a[1000000 + 5];
bool f[1000000 + 5];
int num = 0;
void xs()
{
    for(int i = 2; i <= maxnp; i++)
    {
        if (!isp[i])
            prime[num++] = i;
        for(int j = 0; j <= num && i * prime[j] <= maxnp; j++)
        {
            isp[i * prime[j]] = true;
            if (i % prime[j] == 0)
                 break;
        }
    }
}
bool cal(int l, int r)
{
    memset(f, 0, sizeof(f));
    if (l == 1)
        f[0] = true;
    for(int j = 0; j < num; j++)
    {
        int k = prime[j];
        int i = max(l / k, 2);
        i *= k;
        while(i <= r)
        {
            if (i >= l)
            f[i - l] = true;
            if (i > r - k)
                break;
            i += k;
        }
    }
}
int main()
{
    xs();
    int n, m;
    while(cin>>n>>m)
    {
        int tot = 0;
        cal(n, m);
        int i = n;
        while(i <= m)
        {
           if (!f[i - n])
            a[tot ++] = i;
            if (i == 2147483647)
                break;
            i++;
        }
        int pp = 1;
        if (tot < 2)
        {
            printf("There are no adjacent primes.\n");
        } else
        {
        int mi = a[1] - a[0], ma = a[1] - a[0], lma = a[0], lmi = a[0];
        for(int i = 2; i < tot; i++)
        {
            int k = a[i] - a[i - 1];
            if (k < mi)
            {
                mi = k;
                lmi = a[i - 1];
            }
            if(k > ma)
            {
                ma = k;
                lma = a[i - 1];
            }
        }
       // printf("%d\n", tot);
        printf("%d,%d are closest, %d,%d are most distant.\n", lmi, lmi + mi, lma, lma + ma);
        }
    }
    return 0;
}

POJ 1995 Raising Modulo Numbers 快速幂

#include<cstdio>
#include<iostream>
using namespace std;
int p;
int quick(int a, int b)
{
    a = a % p;
    int ans = 1;
    while (b)
    {
        if (b & 1)
            ans = (ans * a) % p;
        a = (a * a) % p;
        b /= 2;
    }
    return ans;
}
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int n;
        scanf("%d", &p);
        scanf("%d", &n);
        int ans = 0;
        for(int i = 0; i < n; i++)
        {
            int a, b;
            scanf("%d%d", &a, &b);
            ans = (ans + quick(a, b))% p;
        }
         printf("%d\n", ans);
    }
    return 0;
}

[~~~]

我要吐槽一下快速幂,对于a^b,应该先a %= p一下

POJ -3641Pseudoprime numbers(快速幂)

#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
ll p;
ll quick(ll a, ll b)
{
    a = a % p;
    ll ans = 1LL;
    while (b)
    {
        if (b & 1)
            ans = (ans * a) % p;
        a = (a * a) % p;
        b /= 2;
    }
    return ans;
}
bool cal(ll x)
{
    for(int i = 2; i <= sqrt(x); i++)
        if (x % i == 0)
         return false;
    return true;
}
int main()
{
    ll a;
    cin>>p>>a;
    while(p && a)
    {
        if (cal(p) || quick(a, p)!=a)
            printf("no\n"); else
             printf("yes\n");
        cin>>p>>a;
    }
    return 0;
}

同余

#include<cstdio>
#include<iostream>
using namespace std;
typedef long long LL;
LL exgcd(LL a, LL b, LL &x, LL &y)
{
    if (b == 0)
    {
        x = 1;
        y = 0;
        return a;
    }
    LL ans = exgcd(b, a % b, x, y);
    int tmp = x;
    x = y;
    y = tmp - a / b * y;
    return ans;
}
LL cal(LL a, LL b, LL c)
{
    LL x, y;
    LL gcd = exgcd(a, b, x, y);
    if (c % gcd != 0)
        return -1;
    x *= c / gcd;
    b /= gcd;
    if (b < 0)
        b = -b;
    x %= b;
    if (x <= 0)
        x += b;
    return x;
}
int main()
{
    LL x, y, m, n, l, ans;
    cin>>x>>y>>m>>n>>l;
    ans = cal(m - n, l, y - x);
    if (ans < 0)
         printf("Impossible"); else
    cout<<ans;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值