题意:给一个长为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; }