数学编程中有许多有趣的题目,今天我来带领大家研究几道,以便对正在奋力刷题的ACMer有所帮助!
题目:http://poj.org/problem?id=2229
题意:给定一个正整数,求有多少种方法把它写成若干个2幂次的和。
分析:本题可以用递推的思路,我们可以明确,对于一个正整数,它的2的幂次和的表示分情况讨论
(1)如果为奇数,那么在这个表示中一定含有一个1,把这个1减去,就是的情况了。
(2)如果为偶数,那么也分情况,得到。
代码:
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
const int MOD = 1000000000;
const int N = 1000005;
int dp[N];
void Init()
{
dp[1] = 1;
dp[2] = 2;
for(int i = 3; i < N; i++)
{
if(i & 1) dp[i] = dp[i - 1] % MOD;
else dp[i] = (dp[i - 2] + dp[i >> 1]) % MOD;
}
}
int main()
{
int n;
Init();
while(cin>>n)
cout<<dp[n]<<endl;
return 0;
}
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1714
题意:如下图,给定椭圆的标准方程和点的坐标,求红色区域的面积。
分析:首先求直线与椭圆的交点坐标,然后得到面积公式为
根据如下公式
化简后最终结果为
代码:
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
int main()
{
int T;
cin>>T;
while(T--)
{
double a, b, x, y;
cin>>a>>b>>x>>y;
if(y < 0) y = -y;
double x1 = a * b * x / sqrt((a * a * y * y + b * b * x * x));
x1 /= a;
double t = acos(x1);
double area = t * b * a / 2;
cout<<fixed<<setprecision(2)<<area<<endl;
}
return 0;
}
题目:http://acm.hdu.edu.cn/showproblem.php?pid=2554
题意:给定对数,每对数的值分别为,现在要求判断是否存在一个长度为的序列,使得对所有的
数,值为的两个相同数之间所夹的数的个数为。
分析:假设数的第一个位置为,第二个位置为,那么有,继续得到
而对于它们本身会有
这样解得
接下来,只要保证它们是整数就行。
代码:
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
typedef long long LL;
int main()
{
int n;
while(cin>>n && n)
{
if(n % 4 == 0 || (3 * n - 1) % 4 == 0) puts("Y");
else puts("N");
}
return 0;
}
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1214
题意:对于一个有环序列,每次只能对调相邻两位数字,要得到逆序至少需要操作多少次?
分析:在直线上移动很简单,即冒泡排序的方法,所以最少移动次数为
那么,在圆环上又是什么情况呢?事实上在圆环上是把圆环看成两段,分别移动。那么如何分段,答案是尽量
使两段长度相等。证明如下
设总长度为,分段后的长度分别为和,那么得到
要使取得最大值,那么取
代码:
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
typedef long long LL;
int main()
{
int n;
while(cin>>n)
{
int a = n >> 1;
int b = n - a;
int ans = a * (a - 1) / 2 + b * (b - 1) / 2;
cout<<ans<<endl;
}
return 0;
}
题目:http://codeforces.com/problemset/problem/248/B
题意:找出一个最小的位数,使得它的素因子分解中仅含有2,3,5,7,如果不存在则输出-1。
分析:首先小于4的情况很好判断,接下来只研究大于等于4的情况。我们可以发现满足素因子分
解中仅含有2,3,5,7的位数,但不是最小的,当然这个可以继续减去210,直到最小即可。即
变换一下,可以得到最小的位数为
代码:
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
int main()
{
int n;
while(cin>>n)
{
if(n < 3)
{
puts("-1");
continue;
}
if(n == 3)
{
puts("210");
continue;
}
printf("1");
int ans = 50;
for(int i = 1; i <= n - 4; i++)
{
printf("0");
ans = ans * 10 % 210;
}
printf("%03d\n", ans);
}
return 0;
}
题目:UVA10025,给定,其中?代表正负号,求满足条件最小的。
分析:在上述序列中,设所有正数之和为,所有负数之和为,那么得到
继续消去得到
接下来往上枚举即可。
代码:
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
int main()
{
int T;
scanf("%d", &T);
for(int i = 1; i <= T; i++)
{
int k;
scanf("%d", &k);
if(i > 1) puts("");
if(k < 0) k = -k;
int ans = 0;
for(int n = 1; ;n++)
{
ans += n;
if(ans >= k && (ans - k) % 2 == 0)
{
printf("%d\n", n);
break;
}
}
}
return 0;
}
题目:http://acm.hdu.edu.cn/showproblem.php?pid=2563
题意:在一个无限大的二维方格平面中,每次只能移动一个格子,每次只能向上或左右移动,并且踩过的格子会消失。
求走步一共有多少种方案。
分析:设为第步向上的方案数,为第步向左或向右的方案数,为当前的总方案数。
因为向上只有一个方向,所以,而之前向上的可以走两个方向,之前向左或者右的只能按
原来的方向继续走,所以,总数为,最终得到。
代码:
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
typedef long long LL;
const int N = 25;
LL dp[N];
void Init()
{
dp[1] = 3;
dp[2] = 7;
for(int i = 3; i < N; i++)
dp[i] = 2 * dp[i - 1] + dp[i - 2];
}
int main()
{
int T;
Init();
scanf("%d", &T);
while(T--)
{
int n;
scanf("%d", &n);
printf("%lld\n", dp[n]);
}
return 0;
}
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2659
题意:给定两个奇质数和,求如下表达式的值。
分析:考虑如下直线
那么,题目中表达式的两部分分别代表本直线下方和左方整数点的数目,如果与互质,则这条直线上没有整
点,所以不会重复,当然与相等时也是一种情况,最终答案为矩形整点数目的四分之一。
代码:
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
typedef long long LL;
int main()
{
LL p, q;
while(cin>>p>>q)
{
if(p == q) cout<<p * q / 4<<endl;
else cout<<(p - 1) * (q - 1) / 4<<endl;
}
return 0;
}