Part2.4分治

分治,即分而治之,将大问题分解为小问题,分别求解,最后合并结果。

【模板】快速幂

题目描述

给你三个整数 a , b , p a,b,p a,b,p,求 a b   m o d   p a^b \bmod p abmodp

输入格式

输入只有一行三个整数,分别代表 a , b , p a,b,p a,b,p

输出格式

输出一行一个字符串 a^b mod p=s,其中 a , b , p a,b,p a,b,p 分别为题目给定的值, s s s 为运算结果。

样例 #1

样例输入 #1

2 10 9

样例输出 #1

2^10 mod 9=7

提示

样例解释

2 10 = 1024 2^{10} = 1024 210=1024 1024   m o d   9 = 7 1024 \bmod 9 = 7 1024mod9=7

数据规模与约定

对于 100 % 100\% 100% 的数据,保证 0 ≤ a , b < 2 31 0\le a,b < 2^{31} 0a,b<231 a + b > 0 a+b>0 a+b>0 2 ≤ p < 2 31 2 \leq p \lt 2^{31} 2p<231

代码实现

#include<iostream>
using namespace std;
long long QuickPower(long long a,long long b,long long p)
{
	long long ans=1,base=a;
	while(b)
	{
		if(b&1)
		{
			ans*=base;
			ans%=p;	
		}
		base*=base;
		base%=p;
		b>>=1;
	}
	return ans;
}
int main()
{
	long long a,b,p;
	cin>>a>>b>>p;
	cout<<a<<"^"<<b<<" mod "<<p<<"="<<QuickPower(a,b,p);
	return 0;
}

[NOIP1998 普及组] 幂次方

题目描述

任何一个正整数都可以用 2 2 2 的幂次方表示。例如 $137=27+23+2^0 $。

同时约定次方用括号来表示,即 a b a^b ab 可表示为 a ( b ) a(b) a(b)

由此可知, 137 137 137 可表示为 2 ( 7 ) + 2 ( 3 ) + 2 ( 0 ) 2(7)+2(3)+2(0) 2(7)+2(3)+2(0)

进一步:

7 = 2 2 + 2 + 2 0 7= 2^2+2+2^0 7=22+2+20 ( 2 1 2^1 21 2 2 2 表示),并且 3 = 2 + 2 0 3=2+2^0 3=2+20

所以最后 137 137 137 可表示为 2 ( 2 ( 2 ) + 2 + 2 ( 0 ) ) + 2 ( 2 + 2 ( 0 ) ) + 2 ( 0 ) 2(2(2)+2+2(0))+2(2+2(0))+2(0) 2(2(2)+2+2(0))+2(2+2(0))+2(0)

又如 1315 = 2 10 + 2 8 + 2 5 + 2 + 1 1315=2^{10} +2^8 +2^5 +2+1 1315=210+28+25+2+1

所以 1315 1315 1315 最后可表示为 2 ( 2 ( 2 + 2 ( 0 ) ) + 2 ) + 2 ( 2 ( 2 + 2 ( 0 ) ) ) + 2 ( 2 ( 2 ) + 2 ( 0 ) ) + 2 + 2 ( 0 ) 2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0) 2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)

输入格式

一行一个正整数 n n n

输出格式

符合约定的 n n n 0 , 2 0, 2 0,2 表示(在表示中不能有空格)。

样例 #1

样例输入 #1

1315

样例输出 #1

2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)

提示

【数据范围】

对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 2 × 10 4 1 \le n \le 2 \times {10}^4 1n2×104

NOIP1998 普及组 第三题

代码实现

#include<iostream>
using namespace std;
int a[15];
void solve(int x)
{
	int flag=0;
	for(int i=14;i>=0;i--)
	{
		if(x/a[i]==0)continue;
		if(flag)cout<<"+";
		if(i==1)cout<<"2";
		else if(i==0)cout<<"2(0)";
		else{
			cout<<"2(";
			solve(i);
			cout<<")";
		}
		flag=1;
		x-=a[i];
	}
	return ;
} 
int main()
{
	int n;
	cin>>n;
	a[0]=1;
	for(int i=1;i<=14;i++)a[i]=a[i-1]*2;
	solve(n);
	return 0;
}

平面最近点对(加强版)

题目背景

P7883 平面最近点对(加强加强版)

题目描述

给定平面上 n n n 个点,找出其中的一对点的距离,使得在这 n n n 个点的所有点对中,该距离为所有点对中最小的

输入格式

第一行: n n n ,保证 2 ≤ n ≤ 200000 2\le n\le 200000 2n200000

接下来 n n n 行:每行两个实数: x   y x\ y x y ,表示一个点的行坐标和列坐标,中间用一个空格隔开。

输出格式

仅一行,一个实数,表示最短距离,精确到小数点后面 4 4 4 位。

样例 #1

样例输入 #1

3
1 1
1 2
2 2

样例输出 #1

1.0000

提示

数据保证 0 ≤ x , y ≤ 1 0 9 0\le x,y\le 10^9 0x,y109

代码实现

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define MAX_N 200000
#define MMAX 9999999999999
typedef struct Data
{
	double x,y;
};
Data a[MAX_N+5],b[MAX_N+5];
void cpy(Data&a,Data&b)
{
	a.x=b.x;
	a.y=b.y;
	return ;
}
double calc(Data node1,Data node2)
{
	return sqrt((node1.x-node2.x)*(node1.x-node2.x)+(node1.y-node2.y)*(node1.y-node2.y));
}
bool cmpx(Data&a,Data&b)
{
	return a.x<b.x;
}
bool cmpy(Data&a,Data&b)
{
	return a.y<b.y;
}
double solve(int head,int tail)
{
	if(head==tail)return MMAX;
	if(head+1==tail)return calc(a[head],a[tail]);
	int mid=(head+tail)/2;
	double d1=solve(head,mid),d2=solve(mid+1,tail);
	double minn=min(d1,d2);
	int k=0;
	for(int i=head;i<=tail;i++)
	if(abs(a[i].x-a[mid].x)<minn)cpy(b[++k],a[i]);
	sort(b+1,b+1+k,cmpy);
	for(int i=1;i<k;i++)
	for(int j=i+1;j<=k&&b[j].y-b[i].y<minn;j++)
	minn=min(minn,calc(b[i],b[j]));
	return minn;
}
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	scanf("%lf%lf",&a[i].x,&a[i].y);
	sort(a+1,a+1+n,cmpx);
	printf("%.4lf",solve(1,n));
	return 0;
}

[USACO17JAN] Secret Cow Code S

题面翻译

奶牛正在试验秘密代码,并设计了一种方法来创建一个无限长的字符串作为其代码的一部分使用。

给定一个字符串,对字符串进行一次操作(每一次正确的操作,最后一个字符都会成为新的第一个字符),然后把操作后的字符串放到操作前的字符串的后面。也就是说,给定一个初始字符串,之后的每一步都会增加当前字符串的长度。

给定初始字符串和 N N N,请帮助奶牛计算无限字符串中位置为 N N N 的字符。

第一行输入一个字符串。该字符串包含最多 30 30 30 个大写字母,数据保证 N ≤ 1 0 18 N \leq 10^{18} N1018

第二行输入 一个整数 N N N。请注意,数据可能很大,放进一个标准的 32 32 32 位整数容器可能不够,所以你可能要使用一个 64 64 64 位的整数容器(例如,在 C/C++ 中是 long long)。

请输出从初始字符串生成的无限字符串中的下标为 N N N 的字符。第一个字符的下标是 N = 1 N=1 N=1

感谢 @y_z_h 的翻译

题目描述

The cows are experimenting with secret codes, and have devised a method for creating an infinite-length string to be used as part of one of their codes.

Given a string s s s, let F ( s ) F(s) F(s) be s s s followed by s s s “rotated” one character to the right (in a right rotation, the last character of s s s rotates around and becomes the new first character). Given an initial string s s s, the cows build their infinite-length code string by repeatedly applying F F F; each step therefore doubles the length of the current string.

Given the initial string and an index N N N, please help the cows compute the character at the N N Nth position within the infinite code string.

输入格式

The input consists of a single line containing a string followed by N N N. The string consists of at most 30 uppercase characters, and N ≤ 1 0 18 N \leq 10^{18} N1018.

Note that N N N may be too large to fit into a standard 32-bit integer, so you may want to use a 64-bit integer type (e.g., a “long long” in C/C++).

输出格式

Please output the N N Nth character of the infinite code built from the initial string. The first character is N = 1 N=1 N=1.

样例 #1

样例输入 #1

COW 8

样例输出 #1

C

提示

In this example, the initial string COW expands as follows:

COW -> COWWCO -> COWWCOOCOWWC

12345678

代码实现

#include<iostream>
#include<string>
using namespace std;
int main()
{
	string s;
	long long n;
	cin>>s;
	cin>>n;
	long long len1=s.size(),len2=len1;
	while(n>len2)len2*=2;
	len2/=2;
	while(n>len1)
	{
		if(n==len2+1)n-=1;
		else if(n>len2+1)n-=(len2+1);
		len2/=2;
	}
	cout<<s[n-1];
	return 0;
}
  • 16
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值