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;  
    }  



  • 相关阅读:
    Sikuli:创新的图形化编程技术
    缺少对象 WScript 问题解决方法
    TD8.0迁移到QC9.2,自动迁移失败,手动迁移
    QTP使用小技巧
    外部VBS的调用
    mysql 发生系统错误1067的解决方法
    Mysql 本地计算机无法启动 mysql 服务 错误 1067:进程意外终
    windows下mysql忘记root密码的解决方法
    mysql 常用命令用法总结积木学院整理版
    java、c/c++ 、python 等性能比较 杂谈(整理)
  • 原文地址:https://www.cnblogs.com/caiyishuai/p/13271042.html
Copyright © 2011-2022 走看看