zoukankan      html  css  js  c++  java
  • 四川第七届 E Rectangle

    Rectangle

    frog has a piece of paper divided into nn rows and mm columns. Today, she would like to draw a rectangle whose perimeter is not greater than kk.

    There are 8 (out of 9) ways when n = m = 2, k = 6

    There are 88 (out of 99) ways when n=m=2,k=6n=m=2,k=6

    Find the number of ways of drawing.

    Input

    The input consists of multiple tests. For each test:

    The first line contains 33 integer n,m,kn,m,k (1n,m5104,0k1091≤n,m≤5⋅104,0≤k≤109).

    Output

    For each test, write 11 integer which denotes the number of ways of drawing.

    Sample Input

        2 2 6
        1 1 0
        50000 50000 1000000000

    Sample Output

        8
        0
        1562562500625000000
    解析:枚举矩形的长h,然后它在h的方向上就有n-h+1种放法,同时宽的最大值w即为k/2 - h,对于每个0~w的宽度wi,它在w方向上的放法有m-wi+1种,求和即为所求方案数

    我推出了数学公式
    n*m中a*b的种数:(n-a+1)*(m-b+1)+(m-a+1)*(n-b+1)
    这样仍会超时:a不变,b变化,推出一个公式。
    1^2+2^2+3^2+……+n^2=n*(n+1)*(2*t+1)/6;
    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<map>
    #include<queue>
    #include<vector>
    #define  ll long long
    using namespace std;
    int main()
    {
        ll n,m,k;
        while(~scanf("%lld %lld %lld",&n,&m,&k))
        {
            ll s=0;
            ll temp;
            if(k<6&&k>=4) s=n*m;
            else if(k<4) s=0;
            else
            {
                if(n>m)
                {
                    temp=n;
                    n=m;
                    m=temp;
                }
                for(ll a=1;a<=n;a++)
                {
                    ll b=min(k/2-a,m);
                    if(b>=a)
                    {
                        s+=(n-a+1)*((m-a+1)+(m-b+1))*(b-a+1)/2;
                    }
                    b=min(k/2-a,n);
                    if(b>=a)
                    {
                        s+=(m-a+1)*((n-a+1)+(n-b+1))*(b-a+1)/2;
                    }
                }
                ll t=min(k/4,n);
                t=min(t,m);
                ll ss=0;
                ss+=(t*(t+1)*(2*t+1))/6-(t+1)*t*(n+m+2)/2+(n*m+1+n+m)*t;//中间有重复的情况,a=b的算了两次
                s=s-ss;   
            }
            printf("%lld
    ",s);
        }
        return 0;
    }
    也有更简单的思路:
    #include <bits/stdc++.h>  
    using namespace std;  
      
    int main(){  
        #ifdef sxk  
            freopen("in.txt", "r", stdin);  
        #endif // sxk  
      
        long long n, m, k;  
        while(cin>>n>>m>>k){  
            k /= 2;  
            long long ans = 0;  
            for(int h=1; h<=n; h++){  
                int w = k - h;  
                if(w <= 0) break;  
                if(w > m) w = m;  
                ans += (n - h + 1) * (m + m-w+1)*w/2;    //对于每个h,在h方向上n-h+1种,在w方向上枚举wi求和为(m + m-w+1) * w / 2种  
            }  
            cout<<ans<<endl;  
        }  
        return 0;  
    }  



  • 相关阅读:
    youku客户端
    youku服务端
    [计算机网络]从页面输入网址,回车到显示内容,这中间到底经历了什么
    [碎碎念]在嘛,吱一声.吱...
    [数据结构与算法]08 队列( Queue )以及队列实现的三种方式( Java 版)
    过年了,随便说点儿啥
    [碎碎念]为什么要写易维护的代码
    [碎碎念]如何成为更好的自己
    [年终总结]愿你在以后的黑暗时刻,都能想起我
    [数据结构与算法]07 关于单链表环的操作( Java 版)
  • 原文地址:https://www.cnblogs.com/caiyishuai/p/13271042.html
Copyright © 2011-2022 走看看