基础算法2 (快速幂 二分)

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是否为素数 是素数的话输出 no 不是素数再判断式子(a^n)%p==a;若相等,则输出yes,否则输出no
数据量比较大 要用快速幂

AC code

#include<iostream>
typedef long long ll; 
using namespace std;
ll poww(ll x,ll y,ll mod){
	ll ans = 1;
	while(y){
		if(y&1)
			ans = (ans*x)%mod;
			x = (x*x)%mod;
			y>>=1; 
	}
	return ans;
}
bool sushu(int n)
{
	for(int i = 2;i*i<=n;i++)
	{
		if(n%i==0)
			return 0;
	}
	return 1;
}
int main()
{
	ll a,p;
	while(cin>>p>>a&&p&&a){
		if(sushu(p))
		{
			cout<<"no"<<endl;
			continue;//如果p是素数 直接输出no
		}
		else 
		{
			if(poww(a,p,p) == a)
				cout<<"yes"<<endl;
			else
				cout<<"no"<<endl;
		}
	}
} 

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 AiBi 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

快速幂模板题 直接上代码

AC code

#include<iostream>
#include<cmath>
typedef long long ll; 
using namespace std;
ll m,a,b;
ll poww(ll x,ll y)
{
	ll res = 1;
	while(y){
		if(y&1)
			res = (res*x)%m;
		x = (x*x)%m;
		y>>=1;
	}
	return res;
}

int main()
{
	int t,h;
	cin>>t;
	while(t--){
		ll ans = 0;
		cin>>m>>h;
		for(int i=1;i<=h;i++){
			cin>>a>>b;
			ans += poww(a,b);
			ans %= m;
		}
		cout<<ans<<endl;
	}
	return 0;
}

C - 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,计算{1,2,3,4…n}中有多少个子集合 使其集合元素相加是偶数
找一下规律
2 1
3 3
4 7
5 15 即为2^(n-1)-1

#include<iostream>
#include<cmath>
typedef long long ll;
const int mod = 1000000007;
using namespace std;
ll poww(ll x,ll y){
	ll ans = 1;
	while(y){
		if(y&1)
			ans = (ans*x)%mod;
			x = (x*x)%mod;
			y>>=1; 
	}
	return ans;
}
int main()
{
	int t;
	ll n;
	cin>>t;
	while(t--)
	{
		cin>>n;
		cout<<poww(2,n-1)-1<<endl;
	}
	return 0;
}

D - Distribution money

AFA want to distribution her money to somebody.She divide her money into n same parts.One who want to get the money can get more than one part.But if one man’s money is more than the sum of all others’.He shoule be punished.Each one who get a part of money would write down his ID on that part.
Input
There are multiply cases.
For each case,there is a single integer n(1<=n<=1000) in first line.
In second line,there are n integer a1,a2…an(0<=ai<10000)ai is the the ith man’s ID.
Output
Output ID of the man who should be punished.
If nobody should be punished,output -1.
Sample Input
3
1 1 2
4
2 1 4 3
Sample Output
1
-1

一道模拟题
输入 n 表示有n份工资,n个数ai(0 <= ai <10000),表示ai这个人领了一份,问最后是否有人领的工资大于其他所有人的总和,有就输出他的编号 ,否则输出-1。
直接判断记录每个人领的次数为x,判断是否有 x > (n-x)即可

#include <cstring>
#include <iostream>
#include <cmath>
#define N 10001
using namespace std;
int a[N];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        memset(a,0,sizeof(a));//初始化
      for(int i=0;i<n;i++)
      {
          int x;
          scanf("%d",&x);
          a[x]++;//记录
      }
      int ans=-1;
      for(int i=0;i<N;i++)
      {
          if(a[i]>(n-a[i]))
          {
              ans=i;
              break;
          }
      }
      printf("%d\n",ans);
    }
    return 0;
}

E - Rightmost Digit

Given a positive integer N, you should output the most right digit of N^N.
Input
The input contains several test cases. The first line of the input is a single integer T which is the number of test cases. T test cases follow.
Each test case contains a single positive integer N(1<=N<=1,000,000,000).
Output
For each test case, you should output the rightmost digit of N^N.
Sample Input
2
3
4
Sample Output
7
6
Hint
In the first case, 3 * 3 * 3 = 27, so the rightmost digit is 7.
In the second case, 4 * 4 * 4 * 4 = 256, so the rightmost digit is 6.

快速幂模板题 求个位数即10取模

#include<iostream>
#include<cstring>
#define maxn 10001
typedef long long ll; 
ll poww(ll x,ll y,int mod){
	ll ans = 1;
	while(y){
		if(y&1)
			ans = (ans*x)%mod;
			x = (x*x)%mod;
			y>>=1; 
	}
	return ans;
}
using namespace std;
int main()
{
	ll t,n;
	cin>>t;
	while(t--){
		cin>>n;
		cout<<poww(n,n,10)<<endl;
	}
	return 0;
}

然而这道题也还可以通过找规律实现

#include<iostream>
using namespace std;
int solve[20] = { 0, 1, 4, 7, 6, 5, 6, 3, 6, 9, 0, 1, 6, 3, 6, 5, 6, 7, 4, 9 };
int n, t;
int main()
{
	cin >> t;
	while (t--) {
		cin>>n;
		cout << solve[n % 20] << endl;
	}
	return 0;
}

F - 人见人爱A^B

求A^B的最后三位数表示的整数。
说明:A^B的含义是“A的B次方”
Input
输入数据包含多个测试实例,每个实例占一行,由两个正整数A和B组成(1<=A,B<=10000),如果A=0, B=0,则表示输入数据的结束,不做处理。
Output
对于每个测试实例,请输出A^B的最后三位表示的整数,每个输出占一行。
Sample Input
2 3
12 6
6789 10000
0 0
Sample Output
8
984
1

快速幂模板题 留三位即对1000取模

#include<iostream>
#include<cmath>
typedef long long ll;
using namespace std;
ll poww(int x,int y,int mod){
	ll ans = 1;
	while(y){
		if(y&1)
			ans = (ans*x)%mod;
			x = (x*x)%mod;
			y>>=1; 
	}
	return ans;
}
int main()
{
    int a,b;
	long long res;
    while(cin>>a>>b&&a&&b){
        res = poww(a,b,1000);
        cout<<res<<endl;
    }
}

G - Trailing Zeroes (III)

You task is to find minimal natural number N, so that N! contains exactly Q zeroes on the trail in decimal notation. As you know N! = 12…*N. For example, 5! = 120, 120 contains one zero on the trail.
Input
Input starts with an integer T (≤ 10000), denoting the number of test cases.
Each case contains an integer Q (1 ≤ Q ≤ 108) in a line.
Output
For each case, print the case number and N. If no solution is found then print ‘impossible’.
Sample Input
3
1
2
5
Sample Output
Case 1: 5
Case 2: 10
Case 3: impossible

有几个零就是看能分解出几个5,所以用二分查找是否存在能分解出n个5的数

#include<iostream>
typedef long long ll;
using namespace std;
ll findd(ll x){
	ll cnt=0;
	while(x){
		cnt+=x/5;//cnt-每次商的累加
		x/=5;
	}
	return cnt;
}
int main()
{
	int t,cnt = 1;
	cin>>t;
	while(t--)
	{
		ll a;
		cin>>a;
		ll l = 0,r = 5000000000,mid,ans;
		while(r>=l)
		{
			mid = (l+r)/2;
			if(findd(mid)>=a)
			{
				ans = mid;
				r = mid-1;
			}
			else
			{
				l = mid+1;
			}
		}
		if(findd(ans)!=a)//若不能找到
		{
			cout<<"Case "<<cnt<<": "<<"impossible"<<endl;
			cnt++;
		}
		else
		{
			cout<<"Case "<<cnt<<": "<<ans<<endl;
			cnt++;		
		}
	}	
		return 0;
} 

H - Pie

My birthday is coming up and traditionally I’m serving pie. Not just one pie, no, I have a number N of them, of various tastes and of various sizes. F of my friends are coming to my party and each of them gets a piece of pie. This should be one piece of one pie, not several small pieces since that looks messy. This piece can be one whole pie though.
My friends are very annoying and if one of them gets a bigger piece than the others, they start complaining. Therefore all of them should get equally sized (but not necessarily equally shaped) pieces, even if this leads to some pie getting spoiled (which is better than spoiling the party). Of course, I want a piece of pie for myself too, and that piece should also be of the same size.
What is the largest possible piece size all of us can get? All the pies are cylindrical in shape and they all have the same height 1, but the radii of the pies can be different.
Input
One line with a positive integer: the number of test cases. Then for each test case:
—One line with two integers N and F with 1 <= N, F <= 10 000: the number of pies and the number of friends.
—One line with N integers ri with 1 <= ri <= 10 000: the radii of the pies.
Output
For each test case, output one line with the largest possible volume V such that me and my friends can all get a pie piece of size V. The answer should be given as a floating point number with an absolute error of at most 10^(-3).
Sample Input
3
3 3
4 3 3
1 24
5
10 5
1 4 2 3 4 5 6 5 4 2
Sample Output
25.1327
3.1416
50.2655

题意
输入N,测试实例的个数,然后是n,m,分别为蛋糕的数量和人数,接着是每块蛋糕的半径,要将蛋糕分给没个人(包括他自己),输出每个人可以分到的最大面积。

这道题我们采用二分法。首先我们将蛋糕的面积加和再除以人数为X,这是每个人可以分到的最大的面积,然后我们以l=0,r=X,之后就进行二分,二分结束的条件是(r-l)<1e-5,每次二分用每块蛋糕面积除以mid再加和,通过人数比较来决定mid应该向哪个方向移动。

#include<iostream>
#include<iomanip>
#define PI 3.1415926535898 
using namespace std;
int main()
{
	int t,n,f,r,summ;
	double a[10005]; 
	double min,max,mid,ans,sum=0;
	cin>>t;
	while(t--)
	{
		cin>>n>>f;
		for(int i=0;i<n;i++)
		{
			cin>>r;
			a[i] = r*r*PI;
			sum+=a[i];
		}
		min = 0;
		max = sum/1.0*(f+1);//最大体积 自己也吃 
		while(max-min>1e-5)
		{
			mid = (min+max)/2;
			summ=0;//能分人数 
			for(int i=0;i<n;i++)
				summ+=(int)(a[i]/mid);//每个馅饼的体积/能分到最大的体积=能分到的人数 
			if(summ>=(f+1))
				min = mid;
			else
				max = mid;
		}
		cout<<fixed<<setprecision(4)<<mid<<endl;
	}
		return 0;
}

I - Can you solve this equation?

Now,given the equation 8x^4 + 7x^3 + 2x^2 + 3x + 6 == Y,can you find its solution between 0 and 100;
Now please try your lucky.
Input
The first line of the input contains an integer T(1<=T<=100) which means the number of test cases. Then T lines follow, each line has a real number Y (fabs(Y) <= 1e10);
Output
For each test case, you should just output one real number(accurate up to 4 decimal places),which is the solution of the equation,or “No solution!”,if there is no solution for the equation between 0 and 100.
Sample Input
2
100
-4
Sample Output
1.6152
No solution!

二分解方程!当头和尾逼近所设的精度时,答案就出来了

#include<cstdio>
#include<iostream>
#include<iomanip>
#include<cmath>
using namespace std;
double f(double n)
{
    return 8*pow(n,4)+7*pow(n,3)+2*pow(n,2)+3*n+6;
}
int main()
{
    int t;
    double l,r,mid,y;
    cin>>t;
    while(t--)
    {
        mid=0;
        cin>>y;
        l=0.0;r=100.0;
        if(f(0.0)>y||f(100.0)<y)//不满足条件
        {
            cout<<"No solution!"<<endl;
        }
        else
        {
            while(r-l>1e-6)
            {
                mid=(l+r)/2;
                if(f(mid)>y)
                {
                    r=mid;
                }
                else
                {
                    l=mid;
                }
            }
           printf("%.4lf\n",mid);
        }
    }
}

J - Subsequence

A sequence of N positive integers (10 < N < 100 000), each of them less than or equal 10000, and a positive integer S (S < 100 000 000) are given. Write a program to find the minimal length of the subsequence of consecutive elements of the sequence, the sum of which is greater than or equal to S.
Input
The first line is the number of test cases. For each test case the program has to read the numbers N and S, separated by an interval, from the first line. The numbers of the sequence are given in the second line of the test case, separated by intervals. The input will finish with the end of file.
Output
For each the case the program has to print the result on separate line of the output file.if no answer, print 0.
Sample Input
2
10 15
5 1 3 5 10 7 4 9 2 8
5 11
1 2 3 4 5
Sample Output
2
3

题意
有n个正整数组成一个序列。给定整数S,求长度最短的连续序列,使它们的和大于或等于S。

啊刚开始看错了题意 我根据题面的两个数据 以为是整个数列中 至少多少个数的序列的和大于等于S 我就铁憨憨了 直接sort从大到小排序找前几个之和大于等于S 那就WA呗 对不起 我蠢

这道题我用的二分 前缀和 没有用尺取法 之后重写一遍
lower_bound()返回值是一个迭代器,返回指向比key大的第一个值的位置

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int a[100011],b[100011];
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		memset(b,0,sizeof(b));
		int n,s;
		cin>>n>>s;
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];
			b[i]=b[i-1]+a[i];//前缀和		
		}
		if(b[n]<s)//所有和都小于S 铁定错		
		{
			cout<<0<<endl;
			continue;
		}
		int ans;
		ans=lower_bound(b+1,b+n+1,b[1]+s)-b;//b数组由于是叠加起来的,所以按照从小到大的顺序排列,找到第一个大于等于b[1]+s的位置下标
		int l=ans-1;
		for(int i=2;i<=n;i++)
		{
			if(b[n]-b[i]<s)//从右往左找
				break;
			ans=lower_bound(b+1,b+n+1,b[i]+s)-b; 
			if(ans-i<l)//最小序列
				l=ans-i;
		}
		cout<<l<<endl;
	}
	return 0;
}

Over。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值