zoukankan      html  css  js  c++  java
  • HDU4466_Triangle

    今天比赛做的一个题目,不过今天终于感受到了复旦题目有多坑了。

    题目的意思是给你一段长为n个单位长度的直线,你可以选择任意连续单位长度的线段组成三角形,可以组成任意你可以组成任意多个三角形,且要求其中所有的三角形相似。现在要你求出,总共有多少种三角形的情况。 详情见题目。

    题目的意思明白了以后就可以开始思考具体怎么解题了。

    比赛开始的时候我也很费解,到底怎么求出所有的排列组合的情况。

    一开始我是这样考虑的,要使得最终的每一个三角形都相似,那么其中所有的三角形必须有一个不小于3的公约数,但是对于三角形的边长怎么不重复地搞出来还是没有办法。

    其实是这样来搞的。我们用一个函数f(i)来表示周长为i的独特的三角形的数目有多少。我这里所谓的“独特”,其实是其不会与任何一个周长小于i的三角形相似。但是后来仔细一想就知道是gcd(a,b,c)=1,也就是说三角形的三边互质。同时f[i]表示的只是a不大于b,b不大于c的种类数量。

    对于某一个i,其独特的种类数可以用类似容斥原理的方法求得。

    什么意思呢?

    另某一个中间变量tot=[sigama]f(x),(x为A的所有的约数),那么f(A)=count(x)-tot。这里count(x)表示周长为x的三角形的总数。

    这样就可以得到所有的独特数了。

    题目剩下的就比较简单了,枚举独特的三角形的时候对于后面的每一个独立的独特单元,它都有两种组合情况,要么与前面的组合,要么不组合,这样就可以快速幂解决了。

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 #define maxn 5000500
     5 #define M 1000000007
     6 #define ll long long
     7 using namespace std;
     8 
     9 ll f[maxn];
    10 
    11 ll count(ll x)
    12 {
    13     ll tot=0;
    14     for (int i=1; i<=x/3; i++)
    15     {
    16         int tep=x-i;
    17         if (tep/2>=max(i,(tep-i)/2+1))
    18         {
    19             tot=(tot+tep/2-max(i,(tep-i)/2+1)+1);
    20             if (tot>=M) tot-=M;
    21         }
    26     }
    27     return tot;
    28 }
    29 
    30 ll get(ll x) 
    31 {
    32     if (f[x]!=0) return f[x];
    33     ll tot=0;
    34     for (int i=3; i<=x/2; i++)
    35         if (x%i==0)
    36         {
    37             tot=(tot+get(i));
    38             if (tot>=M) tot-=M;
    39         }
    42     f[x]=count(x)-tot;
    43     if (f[x]<0) f[x]+=M;
    44     return f[x];
    45 }
    46 
    47 ll power(ll x,ll y)
    48 {
    49     ll tot=1;
    50     while (y)
    51     {
    52         if (y&1) tot=(tot*x)%M;
    53         x=(x*x)%M;
    54         y>>=1;
    55     }
    56     return tot;
    57 }
    58 
    59 int main()
    60 {
    61     ll n,ans,tep,cas=0;
    62     while (scanf("%I64d",&n)!=EOF)
    63     {
    64         ans=0;
    65         for (int i=1; i*i<=n; i++)
    66         {
    67             if (n%i==0)
    68             {
    69                 tep=get(i); 
    70                 tep=(tep*power(2,n/i-1))%M;
    71                 ans+=tep;
    72                 if (ans>=M) ans-=M;
    73 
    74                 if (i*i!=n)
    75                 {
    76                     tep=get(n/i);
    77                     tep=(tep*power(2,i-1))%M;
    78                     ans+=tep;
    79                     if (ans>=M) ans-=M;
    80                 }
    81             }
    82         }
    83 
    84         printf("Case %I64d: %I64d
    ",++cas,ans);
    85     }
    86     return 0;
    87 }
    如有转载,请注明出处(http://www.cnblogs.com/lochan)
  • 相关阅读:
    网络七层模型
    datagaridview添加序号
    sqlserver查询数据库所有字段和表的关系
    Code Project精彩系列转
    操作不同线程中的控件
    PetaPoco数据读写并发时出错
    浮点型float数据强制转换成int整型
    PetaPoco微型ORM的使用错误记录
    EF出现基础提供程序在 Open 上失败
    Python中random模块
  • 原文地址:https://www.cnblogs.com/lochan/p/3397869.html
Copyright © 2011-2022 走看看