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

A


Some positive integers can be represented by a sum of one or more consecutive prime numbers. How many such representations does a given positive integer have? For example, the integer 53 has two representations 5 + 7 + 11 + 13 + 17 and 53. The integer 41 has three representations 2+3+5+7+11+13, 11+13+17, and 41. The integer 3 has only one representation, which is 3. The integer 20 has no such representations. Note that summands must be consecutive prime 
numbers, so neither 7 + 13 nor 3 + 5 + 5 + 7 is a valid representation for the integer 20. 
Your mission is to write a program that reports the number of representations for the given positive integer.
Input
The input is a sequence of positive integers each in a separate line. The integers are between 2 and 10 000, inclusive. The end of the input is indicated by a zero.
Output
The output should be composed of lines each corresponding to an input line except the last zero. An output line includes the number of representations for the input integer as the sum of one or more consecutive prime numbers. No other characters should be inserted in the output.
Sample Input
2
3
17
41
20
666
12
53
0
Sample Output
1
1
2
3
0
0
1
2


/*
题目大意:一个数可以分成多个连续质数的和(包括这个数本身,算一种),求一共有多少种分法。
解题思路:先用素筛找到足够用的素数,然后暴力即可。
*/
#include <cstdio>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int mark[10010];
int prime[10010];
int Prime()
{
    int index = 0;
    memset(mark,0,sizeof(mark));
    for(int i = 2;i<10010;i++)
    {
        if(mark[i]==0)
            prime[index++] = i;
        for(int j = 0;j<index&&prime[j]*i<10010;j++)
        {
            mark[i*prime[j]]=1;             //所有素数的倍数一律去掉
            if(i%prime[j]==0)               //i%prime[j]==0 时 因为prime数组 中的素数是递增的,当 i 能整除 prime[j],
                                           // 那么 i*prime[j+1] 这个合数肯定被 prime[j] 乘以某个数筛掉。
                                            //因为i中含有prime[j], prime[j] 比 prime[j+1] 小。接下去的素数同理。所以不用筛下去了。
                break;
        }
    }
    return index;
}
int main()
{
    int num;
    while(cin>>num,num!=0)
    {
        Prime();
        int sum=0,c=0,point=0;
        for(int i=0;sum<=num&&prime[point]<=num;i++)
        {
            if(sum==num)
            {
                c++;
                point++;
                i=point-1;
                sum=0;
                continue;
            }
            if(sum+prime[i]>num&&sum<num)   //i=point-1 指向下一个重新遍历
            {
                point++;
                i=point-1;
                sum=0;
                continue;
            }
            sum+=prime[i];

        }
        cout<<c<<endl;
    }
    return 0;
}


 B

 

The branch of mathematics called number theory is about properties of numbers. One of the areas that has captured the interest of number theoreticians for thousands of years is the question of primality. A prime number is a number that is has no proper factors (it is only evenly divisible by 1 and itself). The first prime numbers are 2,3,5,7 but they quickly become less frequent. One of the interesting questions is how dense they are in various ranges. Adjacent primes are two numbers that are both primes, but there are no other prime numbers between the adjacent primes. For example, 2,3 are the only adjacent primes that are also adjacent numbers. 
Your program is given 2 numbers: L and U (1<=L< U<=2,147,483,647), and you are to find the two adjacent primes C1 and C2 (L<=C1< C2<=U) that are closest (i.e. C2-C1 is the minimum). If there are other pairs that are the same distance apart, use the first pair. You are also to find the two adjacent primes D1 and D2 (L<=D1< D2<=U) where D1 and D2 are as distant from each other as possible (again choosing the first pair if there is a tie).
Input
Each line of input will contain two positive integers, L and U, with L < U. The difference between L and U will not exceed 1,000,000.
Output
For each L and U, the output will either be the statement that there are no adjacent primes (because there are less than two primes between the two given numbers) or a line giving the two pairs of adjacent primes.
Sample Input
2 17
14 17
Sample Output
2,3 are closest, 7,11 are most distant.
There are no adjacent primes.



/*
题目大意:给一个范围L~U,输出其中相邻质数差值最大的和最小的,结果相同输出第一组
解题思路:还是素筛+暴力,但是这个题数据范围很大,需要进行优化。
第一是求出int范围内的素数,没办法直接开那么大的数组,如果一个合数的一个公因数大于2^16,那么另一个公因数必定小于2^16次方,所以求出2^16次方内的素数,
然后通过乘倍数,找到int范围内的合数,用f标记一下,未标记的就是素数了。
第二是数组下标需要优化,下标无法直接用L~U,因此做一个转移,变成0~U-L。
*/
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <cstdio>
#define Max 65536
using namespace std;
int mark[Max];
int prime[Max];
int f[1000010];
int index = 0;
void Prime()      //筛除65536以内的质数
{
    memset(mark,0,sizeof(mark));
    for(int i = 2;i<Max;i++)
    {
        if(mark[i]==0)
            prime[index++]=i;
        for(int j = 0;j<index&&i*prime[j]<Max;j++)
        {
            mark[i*prime[j]]=1;
            if(i%prime[j]==0)
                break;
        }
    }
}

int main()
{
    int l,u;
    Prime();
    while(cin>>l>>u)
    {
        memset(f,0,sizeof(f));
        if(l==1) l=2;
        for(int i = 0;i<index;i++)
        {
            int a = l/prime[i];
            int b = u/prime[i];
            for(int j = a;j<=b;j++)
            {
                if(j>1)
                f[j*prime[i]-l] = 1;   //所有范围内质数的倍数一律标记为1
            }
        }
        int n=-1,max_=-1,min_=1e9,min_1,min_2,max_1,max_2;  //max min 记录差值,  _1 _2记录数
        for(int i = 0;i<=u-l;i++)
        {
            if(f[i]==0)   //保证仅对素数进行操作
            {
                if(n==-1)
                {
                    n=i;continue;
                }
                if(max_<i-n)  //因为相同数据取第一组,所以用<而非≤
                {
                    max_=i-n;  max_1=n+l;  max_2=i+l;  //记录时记得把偏移量再加回来!
                }
                if(min_>i-n)
                {
                    min_=i-n;  min_1=n+l;  min_2=i+l;
                }
                n=i;
            }
        }
        if(max_==-1)
            cout<<"There are no adjacent primes.\n";
        else
            printf("%d,%d are closest, %d,%d are most distant.\n",min_1,min_2,max_1,max_2);
    }
    return 0;
}

 C

 

People are different. Some secretly read magazines full of interesting girls' pictures, others create an A-bomb in their cellar, others like using Windows, and some like difficult mathematical games. Latest marketing research shows, that this market segment was so far underestimated and that there is lack of such games. This kind of game was thus included into the KOKODáKH. The rules follow: 

Each player chooses two numbers Ai and Bi and writes them on a slip of paper. Others cannot see the numbers. In a given moment all players show their numbers to the others. The goal is to determine the sum of all expressions Ai  Bi from all players including oneself and determine the remainder after division by a given number M. The winner is the one who first determines the correct result. According to the players' experience it is possible to increase the difficulty by choosing higher numbers. 

You should write a program that calculates the result and is able to find out who won the game. 

Input
The input consists of Z assignments. The number of them is given by the single positive integer Z appearing on the first line of input. Then the assignements follow. Each assignement begins with line containing an integer M (1 <= M <= 45000). The sum will be divided by this number. Next line contains number of players H (1 <= H <= 45000). Next exactly H lines follow. On each line, there are exactly two numbers Ai and Bi separated by space. Both numbers cannot be equal zero at the same time.
Output
For each assingnement there is the only one line of output. On this line, there is a number, the result of expression 

(A1B1+A2B2+ ... +AHBH)mod M.

Sample Input
3
16
4
2 3
3 4
4 5
5 6
36123
1
2374859 3029382
17
1
3 18132
Sample Output
2
13195
13
/*
题目大意:计算 (A1^B1+A2^B2+ ... +AH^BH)mod M.
解题思路:裸的快速幂 直接套公式.... QAQ不过我好像理解不够深刻  什么同余公式什么转换blabla的。。有点蒙...
*/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
int pow_mod(int a,int b,int m)   //快速幂套路
{
    int ans = 1;
    a=a%m;
    while(b>0)
    {
        if(b%2==1)
            ans=(ans*a)%m;
        b=b/2;
        a=(a*a)%m;
    }
    return ans;
}

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int mod;cin>>mod;
        int n;cin>>n;
        int ans=0;
        while(n--)
        {
            int a,b; cin>>a>>b;
            ans += pow_mod(a,b,mod);
        }
        cout<<ans%mod<<endl;
    }
}


D

Fermat's theorem states that for any prime number p and for any integer a > 1, ap =a (mod p). That is, if we raise a to the pth power and divide by p, the remainder isa. Some (but not very many) non-prime values of p, known as base-pseudoprimes, have this property for some a. (And some, known as Carmichael Numbers, are base-apseudoprimes for all a.)

Given 2 < p ≤ 1000000000 and 1 < a < p, determine whether or not p is a base-apseudoprime.

Input

Input contains several test cases followed by a line containing "0 0". Each test case consists of a line containing p and a.

Output

For each test case, output "yes" if p is a base-a pseudoprime; otherwise output "no".

Sample Input
3 2
10 3
341 2
341 3
1105 2
1105 3
0 0
Sample Output
no
no
yes
no
yes
yes

/*
题目大意:如果pow(a,p)=a%p 并且p不是素数,输出yes 否则输出no 0 0 结束输入
解题思路:一个需要开longlong快速幂..
*/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
long long pow_mod(long long a,long long b,long long m)   //快速幂
{
    long long ans = 1;
    a=a%m;
    while(b>0)
    {
        if(b%2==1)
            ans=(ans*a)%m;
        b=b/2;
        a=(a*a)%m;
    }
    return ans;
}

bool isPrime(long long a)  //判断素数
{
    for(long long i = 2;i<=(long long)sqrt((double)a)+1;i++)       //!!!sqrt(double)...需要cast一下
    {
        if(a%i==0)
            return false;
    }
    return true;

}
int main()
{
    long long p,a;
    while(cin>>p>>a)
    {
        if(a==0&&p==0)
        {
         return 0;
        }
        if(isPrime(p))
        {
            cout<<"no"<<endl;
        }
        else
        {
            if(pow_mod(a,p,p)==a)
                cout<<"yes"<<endl;
            else
                cout<<"no"<<endl;
        }
    }
    return 0;
}


E

 

两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面。它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止。可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置。不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰到对方的。但是除非这两只青蛙在同一时间跳到同一点上,不然是永远都不可能碰面的。为了帮助这两只乐观的青蛙,你被要求写一个程序来判断这两只青蛙是否能够碰面,会在什么时候碰面。 
我们把这两只青蛙分别叫做青蛙A和青蛙B,并且规定纬度线上东经0度处为原点,由东往西为正方向,单位长度1米,这样我们就得到了一条首尾相接的数轴。设青蛙A的出发点坐标是x,青蛙B的出发点坐标是y。青蛙A一次能跳m米,青蛙B一次能跳n米,两只青蛙跳一次所花费的时间相同。纬度线总长L米。现在要你求出它们跳了几次以后才会碰面。 
Input
输入只包括一行5个整数x,y,m,n,L,其中x≠y < 2000000000,0 < m、n < 2000000000,0 < L < 2100000000。
Output
输出碰面所需要的跳跃次数,如果永远不可能碰面则输出一行"Impossible"
Sample Input
1 2 3 4 5
Sample Output
4


/*
题目大意:愉快的中文题,俩青蛙均在一个长L的纬线上,各自有一个跳跃能力,从不同点开始相向跳,求它俩跳多少次才能在一起....不能就输出“Impossible”
解题思路:拓展欧几里德算法....还是有点懵逼
跳t次,只要满足 x+tm -(y+tn)= pL (p∈Z)即可,化简一下(n-m)t +Lp = x-y
设n-m=A  x-y=B  即求At+Lp=B     即At=B(mod L) QAQ这个膜的不大懂....然后就可以exgcd了。。。
*/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
long long  x,y,m,n,l,a,b;
long long ex_gcd(long long a,long long b,long long &x,long long &y)
{
    long long t,d;
    if (b==0)
    {
        x=1; y=0; return a;
    }
    d=ex_gcd(b,a%b,x,y);
    t=x; x=y; y=t-a/b*y;
    return d;
}
int main()
{
    long long ar,br;
    while(cin>>x>>y>>m>>n>>l)
    {
        long long M = ex_gcd(n-m,l,ar,br);
        if((x-y)%M||m==n)   //因为起点不同,所以跳跃能力相同 或者 求模不是整数圈均不可能
        {
            cout<<"Impossible"<<endl;
        }
        else
        {
            long long s = l/M;  //这一部分也有点不太懂。 有空再研究研究
            ar = ar*((x-y)/M);
            ar = (ar%s+s)%s;
            cout<<ar<<endl;
        }
    }
}


 


猜你喜欢

转载自blog.csdn.net/jemary_/article/details/54882718
今日推荐