• NOIP模拟题——计数


    【题目描述】
    我们都爱奎奎,最近奎奎给大家出了一道题。
    他告诉了我们一个n*m 的矩阵点,在这个矩阵中的点可以连接成很多线,求
    长度等于某一长度的线的条数。
    【输入】)
    第一行三个正整数n,m,t,第2-t+1 行为所求Wi。
    【输出】
    输出1 行,共t 个数,第i 个数为满足长度Wi 的条数。
    【输入样例1】
    3 3 1 
    1

    例如此为3*3 的矩阵点

    【输出样例1】
    12
    【输入样例2】
    7 11 1
    5
    【输出样例2】
    168
    【输入样例3】
    3 5 1
    2
    【输出样例3】
    14
    【数据说明】
    测试点数据范围
    1 2 N<=2000;M<=2000;T<=100
    3 4 N<=1000000;M<=1000000;T<=100
    5 6 N<=10000000;M<=10000000;T<=100
    7 8 N<=100000000;M<=100000000;T<=100
    9 10 N<=1000000000;M<=1000000000;T<=100
    W<=2max(n,m);

    这道题就是找勾股数,但是太难想了。

    先考虑直线水平和竖直的情况:

    if(n>x)
    ans+=(n-x)*m;
    if(m>x)
    ans+=(m-x)*n;

    在考虑斜着的情况:

    我们设要找的长度为r,则设x²+y²=r²

    得到x=sqrt((r+y)*(r-y))

    设d=gcd(r+y,r-y),A=(r-y)/d,B=(r+y)/d

    得到x=d*sqrt(A*B),推出A*B是完全平方数,又因为A,B是两数除以最大公因数

    得出:A、B是互质的完全平方数

    A+B=2*r/d得出(A+B)*d=2*r

    枚举d从1~sqrt(2*r)、2*r%d=0(原因:若d大于根号2r后,相当于A+B的值和d的值颠倒,重复算了)

    再枚举a从1~sqrt(r/d)——保证A<B,再判断B是否是完全平方数

    若满足,联立A=(r-y)/d,B=(r+y)/d得:

    y=(A-B)*d/2,通过r和y得出x

    再算时间复杂度。枚举d用根号2*r,约5*1e4

    再枚举1~根号r/d,应该大于100,再乘上100组数据,超时。

    但为什么不超时?

    因为d的取值不可能是到根号2*r,所以后面的循环次数也大幅降低了。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cmath>
     5 using namespace std;
     6 int n,m,t;
     7 int gcd(int x,int y)
     8 {
     9     if(y==0)return x;
    10     return gcd(y,x%y);
    11 }
    12 int main()
    13 {
    14     freopen("amount.in","r",stdin);
    15     freopen("amount.out","w",stdout);
    16     scanf("%d%d%d",&n,&m,&t);
    17     if(n>m)swap(n,m);//n小 
    18     for(int j=1;j<=t;j++)
    19     {
    20         long long x;scanf("%I64d",&x);
    21         long long ans=0;
    22         if(n>x)
    23         ans+=(n-x)*m;
    24         if(m>x)
    25         ans+=(m-x)*n;
    26         for(long long d=1;d*d<=2*x;d++)//枚举d 
    27             if(2*x%d==0)
    28             {
    29                 for(long long a=1;a*a<x/d;a++)
    30                 {
    31                     
    32                     long long A=a*a;
    33                     long long B=2*x/d-A;
    34                     long long C=int(sqrt(B+0.5));
    35                     if(C*C!=B)continue;//得出A、B
    36                     if(gcd(a,C)!=1)continue;
    37                     long long k1=(B-A)*d/2;
    38                     long long k2=sqrt(x*x-k1*k1+0.5);
    39                     if(k1*k1+k2*k2!=x*x)continue;
    40                     if(k1>k2)continue;
    41                     if(k1<=n&&k2<=m)
    42                     ans+=(n-k1)*(m-k2)*2;
    43                     if(k1<=m&&k2<=n)
    44                     ans+=(n-k2)*(m-k1)*2; 
    45                 }
    46                 long long k=2*x/d;
    47                 if(2*x%k==0)
    48                 for(long long a=1;a*a<x/k;a++)
    49                 {
    50                     long long A=a*a;
    51                     long long B=2*x/k-A;
    52                     long long C=sqrt(B+0.5);
    53                     if(gcd(a,C)!=1)continue;
    54                     if(C*C!=B)continue;//得出A、B
    55                     long long k1=(B-A)*k/2;
    56                     long long k2=sqrt(x*x-k1*k1+0.5);
    57                     if(k1*k1+k2*k2!=x*x)continue;
    58                     if(k1>k2)continue;
    59                     if(k1<=n&&k2<=m)
    60                     ans+=(n-k1)*(m-k2)*2;
    61                     if(k1<=m&&k2<=n)
    62                     ans+=(n-k2)*(m-k1)*2;
    63                 }
    64             }
    65         printf("%I64d ",ans);
    66     }
    67     return 0;
    68 }

    我不爱奎奎。

  • 相关阅读:
    构建单页面应用
    chrome进入控制台时自动进入断点模式的解决方法
    git安装--linux下的安装
    express响应前端ajax请求
    nodejs链接mongodb数据库
    Redis的Java客户端Jedis的八种调用方式(事务、管道、分布式)介绍
    Nginx中如何限制某个IP同一时间段的访问次数
    nodejs && apidoc
    apidoc
    android sdk
  • 原文地址:https://www.cnblogs.com/937337156Zhang/p/6026026.html
Copyright © 2020-2023  润新知