HDU 5047 Sawtooth 公式

题意:在一张纸上,会有N个"M"形的折线相交。问,这些平面相交最多可以将这张纸划分成多少个区域。

思路:

        1.用高中的方法递推就可以啦:现在已经有放了i个"M"形的折线,考虑第i+1个。要想将平面分成最多的区域,应该使第i+1个折线的四条边和其余i个折线的所有边都有交点。这样,会产生4 * 4i个区域。需要注意的是,因为“M”形折线是从纸边界出来的,然后回到纸的边界,这样会再多一个区域。

        按照上面的递推可以得到公式: 8n^2 - 7n + 1;

        2.还有一个偷懒的方法。其实在平面上,不管用什么样的折线分割,得到的最多区域一定是个二次多项式,用待定系数法,找到三个系数的值,直接解方程就可以了。

注意:因为数很大,要用JAVA写,但是你会发现,正常的方法会TLE。这个时候就要开输入输出挂了。

代码如下:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.math.BigInteger;

public class Main
{
    
    public static void main(String args[]) throws IOException
    {
        StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
        PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
        
        in.nextToken();
        int T = (int)in.nval;
        int i = 1;
        while(i <= T) {
            in.nextToken();
            BigInteger a = BigInteger.valueOf((long)in.nval);
            out.println("Case #" + i + ": " + a.multiply(a).shiftLeft(3).subtract(a.multiply(a.valueOf(7))).add(a.ONE));
            i+=1;
        }
        out.flush();
    }
}

或者直接上C++大整数:

#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

struct BigInteger{
    int len;
    int a[30];
    BigInteger(long long n = 0){
        memset(a,0,sizeof(a));
        len = 0;
        for(;n;n /= 10)
            a[len++] = n % 10;
    }
    void print()
    {
        for(int i = len - 1; i >=0; --i)
            printf("%d",a[i]);
    }

};
BigInteger operator +(const BigInteger & A, const BigInteger & B){
        BigInteger C;
        C.len = max(A.len,B.len);
        int r = 0;
        for(int i = 0; i < C.len; ++i){
            r += A.a[i] + B.a[i];
            C.a[i] = r % 10;
            r /= 10;
        }
        while(r){
            C.a[C.len++] = r % 10;
            r /= 10;
        }
        return C;
    }
    BigInteger operator * (const BigInteger & A, const BigInteger & B){
        BigInteger C;
        C.len = A.len + B.len;
        for(int i = 0; i < A.len; ++i){
            int r = 0;
            for(int j = 0; j < B.len; ++j){
                r += A.a[i] * B.a[j] + C.a[i+j];
                C.a[i+j] = r % 10;
                r /= 10;
            }
            C.a[i + B.len] = r;
        }
        while((C.len > 1) && (C.a[C.len-1] == 0)) --C.len;
        return C;
    }


int main(void)
{
    BigInteger eight(8);
    BigInteger two(2);
    BigInteger nine(9);
    int T;
    long long N;
    scanf("%d", &T);
    for(int i = 1; i <= T; ++i){
        scanf("%I64d", &N);
        if(N == 0){
            printf("Case #%d: 1\n",i);
        }
        else{
            N--;
            BigInteger A(N);
            BigInteger ans = eight * A * A + nine * A + two;
            printf("Case #%d: ",i);
            ans.print();
            puts("");
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值