文章目录
问题A:Birthday Cake
题目链接:UVA10167
题目大意及思路:
给出一个半径为100的蛋糕,上面由2*N个樱桃,直线Ax+By=0恰好将蛋糕分成两半的同时,两边的蛋糕上的樱桃也是相同的。
思路: 暴力,枚举,A,B范围在[-500,500]
AC代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include <vector>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<cstring>
using namespace std;
typedef long long ll;
const int N = 50;
struct point{ //用于记录结构体的坐标
int x,y;
};
int main()
{
int num,left,right,find;//num代表一边樱桃的数量
int A=0,B=0;
point p[2*N+5];
while(cin >> num && num)
{
left = right = 0;
find = 0;
for(int i=0; i<num*2; ++i)//输入每个樱桃的坐标
{
cin >> p[i].x;
cin >> p[i].y;
}
for(int i=-500; i < 500; ++i){ // 暴力枚举
for(int j=-500; j < 500; ++j)
{
left=right=0;
if(i*j==0) continue;
for(int k=0; k<num*2; ++k)
{
if(p[k].x > 100 || p[k].y > 100 || p[k].x < -100 || p[k].y < -100 ) continue; //不在蛋糕上
if( p[k].x *i + p[k].y *j == 0) break; // 在直线上,不行
if( p[k].x *i + p[k].y *j > 0) left++; // 统计左边的数量
else right++; //统计右边的数量
}
if(left == right && left + right == num*2){
A=i;
B=j;
find=1;
break;
}
}
if(find==1) break;
}
cout << A << " "<< B << endl;
}
return 0;
}
问题B:Is This Integration ?
题目链接:UVA10209
题目大意:
如图:给出正方形ABCD边长a,分别以正方形的各顶点为园心,a为半径画圆弧,求条纹面积x,星罗面积y,以及剩下的面积z。
易知:
x+4y+4z=a* a;(整个正方形形的面积)
x+3y+2z=a* a *π / 4;(1/4圆的面积)
x+2y+z=(π/3-√3/4)a * a;(中间的正三角形及两个弓形)
可以推出:
x=(1 + π / 3 - √3 ) * a * a
y=( π / 12 + √3 / 2 - 1) a * a
z=(1 - √3 / 4 - π / 6 ) * a * a
参考代码:
#include<iostream>
#include<cmath>
using namespace std;
#define PI acos(-1.0)
int main()
{
double a;
while (cin >> a)
{
double x=a * a * (1 + PI / 3 - sqrt(3.0));
double y=a * a * (PI / 3 + 2 * sqrt(3.0) - 4);
double z=a * a * (-2 * PI / 3 + 4 - sqrt(3.0));
printf("%.3f %.3f %.3f\n",x,y,z);
}
return 0;
}
问题C:Simple division
题目链接:UVA10407
题目大意:
给出若干个数,以0表示结束,求出一个整数,这个整数是这些数的相同余数的最大值。
思路: 如果两个不同的数除以一个除数的余数相同,那么两个不同数的差值一定是除数的整数倍。对于此题,先求出原序列的差分序列,然后求出所有非零元素的__gcd(a,b);
参考1:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+5;
int f[N];
int main()
{
int x,a;
while(cin >> x && x)
{
int id=0,k;
while(true)
{
cin >> a;
if(a==0) break;
f[id++]=a-x;//差分处理
x = a;
}
for( k=0;f[k]==0;k++);//去除多余的零
int g = f[k++];
for(; k < id; ++k){
if(f[k]) g=__gcd(g,f[k]);
}
cout << abs(g) << endl;
}
return 0;
}
参考2:
其实可以一边输入一边处理,可以不用开差分数组,节省了空间
参考代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a,x;
while(cin >> x && x)
{
int g=0;
while(cin >> a && a)
{
int d=x-a;
x = a;
if(d){ // 差值为0,跳过
if(g) g=__gcd(g,d); //求最大值
else g=d;
}
}
cout << abs(g) << endl;
}
return 0;
}
问题D:Euclid Problem
题目链接:UVA10104
题目大意:
题目要求输入两个正整数a和b,要求输出满足ax+by = d(其中d为a与b的最大公约数)这个式子对应的x和y的解
思路:
扩展欧几里得算法(模板…
- 先来欧几里得算法,
其实就是辗转相除法求最大公约数
核心代码:gcd(a , b) = gcd(b , a mod b)
int gcd(int a, int b) return b == 0 ? a : gcd(b, a % b);//据说比普通的算法快
- 扩展欧几里得
定理描述:对于两个不全为0的整数a、b,必存在一组解x,y,使得ax+by==gcd(a,b);
具体代码实现:
int exgcd(int a,int b, int& x, int& y){
int t,d;
if(b==0) {
x=1, y=0;
return a;
}
d=exgcd(b,a%b);
t=x, x=y;
y=t-(a/b)*y;
return d;
}
好了,回到此题(套模板~~) ,参考代码:
#include<iostream>
using namespace std;
int exgcd(int a, int b, int& x, int& y) {
if (b == 0) {
x = 1; y = 0;
return a;
}
int d = exgcd(b, a % b, x, y);
int tmp = x;
x = y;
y = tmp - (a / b) * y;
return d;
}
int main() {
int a, b;
while (cin >> a >> b) {
int x = 0, y = 0;
int d = exgcd(a, b, x, y);
cout << x << ' ' << y << ' ' << d << endl;
}
return 0;
}
问题E:Dead Fraction
题目链接:POJ1930
题目大意:
给出一个小数,确保是无限循环效数,把无限循环小数变最简分数,但不确定循环节是哪几位,要求输出分母最小的分数。
思路: 日本野口哲典在《天哪!数学原来可以这样学》中介绍了如何将循环小数转化成分数的方法,现介绍如下:
1.循环小数0.7272……循环节为7,2两位,因此化为分数为72/99=1/8.即有几位循环数字就除以几个9。又如>0.123123……循环节为1,2,3三位,因此化为分数为123/999=41/333.这种方法只适用于从小数点后第一位就开循环的小数,如果不是从第一位就开始循环的小数,必须用下面的方法。2.循环小数0.41666……先把0.41666……乘以100得41.666……,可以理解为41+0.666……,所以写成分数为41+6/9=41+2/3=125/3.因为开始乘以了100,所以再除以100,即125/3÷100=125/300=5/12.
综上可知公式:
分子:不循环部分*10^(循环节数字个数)+循环节
分母:10^(不循环部分数字个数) *(10^(循环节数字个数)-1)
最后还要记得约分
参考代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include <vector>
#include<stack>
#include<map>
#include<string>
#include<cstring>
using namespace std;
typedef long long ll;
ll Tpow[10];
ll gcd( ll a ,ll b) {
return b==0?a:gcd(b,a%b);
}
void init()
{
int i;
Tpow[0]=1;
for(int i = 1; i < 10; i++){
Tpow[i] = Tpow[i-1]*10;
}
}
int main()
{
char str[200];
ll ans,a,b,c,temp,mina,minb,t,i;
init();
while(~scanf("%s",str)){
if(str[0] == '0' && strlen(str) == 1) break;
ans = 0;
t = 0;
mina = -1, minb = -1;
for( i = 2; str[i] != '.'; i++){
ans = ans*10+str[i] - '0';
t++;
}
for(i = t; i > 0; i--){
c = ans;
b = Tpow[t-i]*(Tpow[i] - 1);
c = c/Tpow[i];
a = ans-c;
temp = gcd(a,b);
if(b/temp<minb || mina == -1){
mina = a/temp;
minb = b/temp;
}
}
cout << mina << "/"<< minb << endl;
}
return 0;
}
问题F:What is the Probability ?
题目链接:UVA10056
题目大意:
从1-n轮回掷骰子,每个人每次有p的概率赢,求出第m个人赢的概率。
概率问题:
参考代码:
#include<iostream>
#include<cmath>
using namespace std;
int s, x, i;
double p;
double ans;
int main() {
cin >> s;
while (s--) {
cin >> x >> p >> i;
if(p==0) ans = 0;
else ans = pow(1 - p, i - 1) * p * (1.0 / (1 - pow(1 - p, x)));
printf("%.4f\n", ans);
}
return 0;
}
问题G:Coin Toss
题目链接:POJ3440
题目大意:
给出了一个n*m的格子,每个格子的边长为t,随意抛一枚硬币并保证硬币的圆心在格子里或格子边上,硬币的直径为c,求硬币覆盖格子的个数的概率。
思路:仔细一想,这不是高中的几何概型概率题嘛!根据分别覆盖1,2,3,4个格子时圆心分部的面积比上总面积就是答案。
参考代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const double PI=acos(-1.0),eps=1e-8;
int main()
{
int x,cnt=0;
cin>>x;
while(x--){
double n,m,t,c,A[5];
scanf("%lf%lf%lf%lf",&n,&m,&t,&c);
A[0]=t*t*n*m;//棋盘面积
A[2] = c*(t-c)*(2*m*n-n-m)+c*(c/2.0)*(2*n+2*m-4);
A[4] = (m-1)*(n-1)*(PI*c*c)/4.0;
A[3] = (m-1)*(n-1)*c*c-(m-1)*(n-1)*(PI*c*c)/4.0;
A[1] = A[0]-A[2]-A[3]-A[4];
printf("Case %d:\n",++cnt);
for(int i=1;i<=4;i++)
printf("Probability of covering %d tile%s = %.4lf%%\n",i,(i==1)?" ":"s",A[i]/A[0]*100.0);
printf("\n");
}
return 0;
}
问题H:498-bis
题目链接:UVA10268
题意:
多项式求值,给出一个多项式,求出这个多项式的导数,并将x带入求值
思路:
听课是说递推式:A(i+1)=A(i)∗x+ai
还不会证明~~~>=<
参考代码:
#include<iostream>
#include<cmath>
using namespace std;
int main(){
int x,a;
char c;
while(~scanf("%d",&x)){
int sum=0,ans = 0;
while(~scanf("%d",&a)){
ans = ans*x+sum;
sum = sum*x+a;
scanf("%c",&c);
if(c=='\n') break;
}
cout<<ans<<endl;
}
}
总结:
- 数论知识太薄弱了~
- 一听就会,一做就废(太真实了;;
- 以后要常回来看看这些数论基础(摸鱼摸鱼QwQ)