暑假培训第二天 GCD&&素筛&&快速幂

A.
题源:A - Pseudoprime numbers
题目:

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 is a. Some (but not very many) non-prime values of p, known as base-a pseudoprimes, have this property for some a. (And some, known as Carmichael Numbers, are base-a pseudoprimes for all a.)

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

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

思路:
这道题关键在于你能不能读懂题
题目的意思是,给你两个数 p,a。让你判断p是不是以a为底的伪素数,顾名思义p首先不能是素数,然后用快速幂判断a^p%p的值和a相等不,如果相等p就是伪素数,不相等就不是
AC代码:

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<cmath>
using namespace std;
typedef long long ll;
const int max=1e6+7;
bool prime(ll x)//普通素数判定模板
{
    for(int i=2;i<sqrt(x);i++)
    {
        if(x%i==0)
        {
            return 0;
        }
    }
    return 1;
}
int pow_mod(ll b,ll c)//快速幂模板
{
    ll ans=1;
    ll mod=c;
    while(c)
    {
        if(c&1) ans=ans*b%mod;
        b=b*b%mod;
        c>>=1;
    }
    return ans;
}
int main()
{
    ll a,p;
    while(scanf("%lld %lld",&p,&a)&&a&&p)
    {
        if(prime(p)) printf("no\n");
        else{
            if(a==pow_mod(a,p))
                printf("yes\n");
            else printf("no\n");
        }
    }
	return 0;
}

B.
题源:Raising Modulo Numbers
题目:

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

思路:
这道题挺简单的,就是给你n组数据,每一组数据以m开头,n排数,每一排两个数 a,b,每一组数以0结尾;求
在这里插入图片描述
如果暴力先用快速幂把括号里面的和算出来,应该会数据太大报错,利用同余定理
如果a≡b(mod m),x≡y(mod m),则a+x≡b+y(mod m)。即可解决;
附超链:::同余定理

AC代码

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<cmath>
using namespace std;
typedef long long ll;
const int max=1e6+7;
int pow_mod(ll a,ll b,ll c)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%c;
        a=a*a%c;
        b>>=1;
    }
    return ans;
}
int main()
{
    int t;
    cin >>t;
    while(t--)
    {
        ll m;
        cin >>m;
        int n;
        cin >>n;
        ll sum=0;
        for(int i=0;i<n;i++)
        {
            ll x,y;
            cin >>x>>y;
            sum+=pow_mod(x,y,m);
        }
        sum=sum%m;
           cout <<sum<<endl;
    }

	return 0;
}

C.
题源:Wolf and Rabbit
题解:

There is a hill with n holes around. The holes are signed from 0 to n-1.

在这里插入图片描述

A rabbit must hide in one of the holes. A wolf searches the rabbit in anticlockwise order. The first hole he get into is the one signed with 0. Then he will get into the hole every m holes. For example, m=2 and n=6, the wolf will get into the holes which are signed 0,2,4,0. If the rabbit hides in the hole which signed 1,3 or 5, she will survive. So we call these holes the safe holes.
Input
The input starts with a positive integer P which indicates the number of test cases. Then on the following P lines,each line consists 2 positive integer m and n(0<m,n<2147483648).
Output
For each input m n, if safe holes exist, you should output “YES”, else output “NO” in a single line.
Sample Input
2
1 2
2 2
Sample Output
NO
YES

思路:
这道题有一个规律,当洞的数目n,和狼每隔m个洞钻进去,两个数如果是互质的,那么兔子就无法逃脱;

AC代码:


#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int INF=0x3f3f3f;
#define top 1000005
const int mod=2147483648;
int gcd(ll a,ll b)
{

    return !b? a:gcd(b,a%b);
}
int main()
{
    int t;
    cin >>t;
    while(t--)
    {

        ll m,n;
        cin >>m>>n;
        if(gcd(m,n)==1)
            cout <<"NO"<<endl;
        else cout<<"YES"<<endl;
    }
    return 0;
}

D.
题源:Cake
题目:

一次生日Party可能有p人或者q人参加,现准备有一个大蛋糕.问最少要将蛋糕切成多少块(每块大小不一定相等),才能使p人或者q人出席的任何一种情况,都能平均将蛋糕分食.
Input
每行有两个数p和q.
Output
输出最少要将蛋糕切成多少块.
Sample Input
2 3
Sample Output
4

Hint
将蛋糕切成大小分别为1/3,1/3,1/6,1/6的四块即满足要求.
当2个人来时,每人可以吃1/3+1/6=1/2 , 1/2块。
当3个人来时,每人可以吃1/6+1/6=1/3 , 1/3, 1/3块。

思路
先份成 p 块,然后再拼到一起,再从原来开始的地方,将蛋糕再分成 q 份,中间肯定会出现完全重合的块数为 k,则此是需要分的块数就是 p + q - k.现在只需要求出 k 即可,k 是 gcd(p,q)

AC代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int INF=0x3f3f3f;
#define top 1000005
const int mod=1000000007;
int gcd(int a,int b)
{

    return !b? a:gcd(b,a%b);
}
int main()
{
    int p,q;
    while(cin >>p>>q)
    {
        cout<<p+q-gcd(p,q)<<endl;
    }
    return 0;
}

E.
题源:又见GCD
题目:

有三个正整数a,b,c(0<a,b,c<10^6),其中c不等于b。若a和c的最大公约数为b,现已知a和b,求满足条件的最小的c。
Input
第一行输入一个n,表示有n组测试数据,接下来的n行,每行输入两个正整数a,b。
Output
输出对应的c,每组测试数据占一行。
Sample Input
2
6 2
12 4
Sample Output
4
8

思路:
直接从b的两倍开始枚举即可;
AC代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
int _gcd(ll a,ll b)
{
    return !b? a:_gcd(b,a%b);
}
int main()
{
    int n;
    cin >>n;
    while(n--)
    {
        ll a,b;
        cin >>a>>b;
        int i;
        for(i=2;_gcd(a,i*b)!=b;i++);
        cout <<b*i<<endl;
    }
    return 0;
}

F.不写了 最小公倍数

G.也不写了 素数判定
H.
题源:分拆素数和
题目:

把一个偶数拆成两个不同素数的和,有几种拆法呢?
Input
输入包含一些正的偶数,其值不会超过10000,个数不会超过500,若遇0,则结束。
Output
对应每个偶数,输出其拆成不同素数的个数,每个结果占一行。
Sample Input
30
26
0
Sample Output
3
2

思路:
暴力把所有的成对的偶数试一遍即可
AC代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
int n;
bool prime(int a)
{
    if(a<2) return false;
    for(int i=2;i<sqrt(a)+1;i++)
    {
        if(a%i==0) return false;
    }
    return true;
}
int main()
{
    while(cin>>n)
    {
        if(n==0) break;
        int sum=0;
        for(int i=2;i<n/2;i++)
        {
            if(prime(i)&&prime(n-i)) sum++;
        }
        cout <<sum<<endl;
    }
    return 0;
}

I.
题源:美素数
题目:

小明对数的研究比较热爱,一谈到数,脑子里就涌现出好多数的问题,今天,小明想考考你对素数的认识。
  问题是这样的:一个十进制数,如果是素数,而且它的各位数字和也是素数,则称之为“美素数”,如29,本身是素数,而且2+9 = 11也是素数,所以它是美素数。
  给定一个区间,你能计算出这个区间内有多少个美素数吗?
Input
第一行输入一个正整数T,表示总共有T组数据(T <= 10000)。
接下来共T行,每行输入两个整数L,R(1<= L <= R <= 1000000),表示区间的左值和右值。
Output
对于每组数据,先输出Case数,然后输出区间内美素数的个数(包括端点值L,R)。
每组数据占一行,具体输出格式参见样例。
Sample Input
3
1 100
2 2
3 19
Sample Output
Case #1: 14
Case #2: 1
Case #3: 4

思路:
由于本题数据较大,如果对于每个数都判断会超时,用素数筛打表就行了;打表过程中可以同时判断他是不是美素数,用另外一个数组来储存截止n为止一共有多少个美素数,如果第n个数是美素数,就让size【n】=k++;最后求区间内的素数,相减即可;
AC代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int INF=0x3f3f3f;
#define top 1000005
int prime[top];
int pp[top];
int sum(ll a)
{
    ll ans=0;
    while(a)
    {
        ans+=a%10;
        a/=10;
    }
    if(prime[ans]==0)
        return 1;
    else return 0;
}
int main()
{

    memset(prime,0,sizeof(prime));
    prime[1]=1;
    prime[0]=1;
    for(int i=2,k=0;i<top;i++)
    {
        if(!prime[i]){
                if(sum(i))
                    k++;
        for(int j=i+i;j<top;j+=i)
            prime[j]=1;
        }
        pp[i]=k;
    }
    int t;
    int s=0;
    cin >>t;
    while(t--)
    {
        int l,r;
        cin >>l>>r;
        printf("Case #%d: %d\n",++s,pp[r]-pp[l-1]);
    }
    return 0;
}

J.
题源:Key Set
题目:

soda has a set S with n integers {1,2,…,n}. A set is called key set if the sum of integers in the set is an even number. He wants to know how many nonempty subsets of S are key set.
Input
There are multiple test cases. The first line of input contains an integer T (1≤T≤105), indicating the number of test cases. For each test case:

The first line contains an integer n (1≤n≤109), the number of integers in the set.
Output
For each test case, output the number of key sets modulo 1000000007.
Sample Input
4
1
2
3
4
Sample Output
0
1
3
7

思路;
有n/2个偶数,n/2个奇数(设n是偶数),可以选取的偶数一共有:C(n/2,0)+C(n/2,1)+……+C(n/2,2)=2(n/2)种情况,而可以选取的奇数有:C(n/2,0)+C(n/2,2)+……+C(n/2,n)=(2n/2)/2种情况,乘起来就好了等于2^(n-1),最后要减去一个空集

作者:月黑风高叶
来源:CSDN
原文:https://blog.csdn.net/csdn364988181/article/details/51548748
版权声明:本文为博主原创文章,转载请附上博文链接!
AC代码:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int INF=0x3f3f3f;
#define top 1000005
const int mod=1000000007;
int pow_mod(ll a,ll b)
{

    ll ans=1;
    a=a%mod;
    while(b)
    {
        if(b&1) ans=ans*a%mod;
        b/=2;
        a=a*a%mod;
    }
    return ans;
}
int main()
{
    int t;
    cin >>t;
    while(t--)
    {
        ll n;
        cin >>n;
        cout<<pow_mod(2,n-1)-1<<endl;
    }
    return 0;
}

K. L.两题都是简单的快速幂;就不写了
K.:人见人爱A^B
L.:Rightmost Digit

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值