HDU4466 Triangle

题意:给一个长为N的铁丝,问你有几种方法将其划分为若干段,使得每一段都能围成一个边长为整数的三角形,并且围成的三角形都相似

思路其实很明显,三角形的周长必定是N的约数,那么答案就是周长C能围城的三角形的数量*[N/C]的拆分数的和。问题是这两个东西怎么求。后者比较简单,打个表就能发现它是2的幂次。前者讨论三条边的关系后可以得出递归式:f[i]=f[i-2]+i/3-i/4。之后容斥一下即可。

#include<bits/stdc++.h>
using namespace std;
#define MAXN 5000000+10
#define MODD 1000000007
const int maxn=MAXN-10;
int n,tot,f[MAXN],pw[MAXN]={1},d[MAXN];
void init(){
    for(int i=1;i<=maxn;i++)
        pw[i]=pw[i-1]*2,pw[i]%=MODD;    
}
int main(){
    init();
    int Case=0;
    while(~scanf("%d",&n)){
        Case++;
        for(int i=2;i<=maxn;i++)f[i]=f[i-2]+i/3-i/4,f[i]%=MODD;
        tot=0;    
        for(int i=1;i*i<=n;i++)
            if(n%i==0){
                if(i*i!=n){
                    d[++tot]=i;
                    d[++tot]=n/i;
                }
                else d[++tot]=i;
            }
        sort(d+1,d+tot+1);
        for(int i=1;i<=tot;i++)
            for(int j=1;j<i;j++)
                if(d[i]%d[j]==0)f[d[i]]-=f[d[j]],f[d[i]]=(f[d[i]]+MODD)%MODD;
        long long ans=0;
        for(int i=1;i<=tot;i++)ans=(ans+(long long)f[d[i]]*pw[n/d[i]-1]%MODD)%MODD;
        printf("Case %d: %lld
",Case,ans);    
    }
    return 0;
}
原文地址:https://www.cnblogs.com/NINGLONG/p/7685100.html