数学经典题目

数学编程中有许多有趣的题目,今天我来带领大家研究几道,以便对正在奋力刷题的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;
}


 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值