三角形顺序不同视为不同方案。
题解:http://www.cnblogs.com/jianglangcaijin/p/3465526.html
#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
#define maxn 5000000
using namespace std;
int dp[maxn+5];
int power[maxn+5];
int main(){
power[0]=1;
for(int i=1;i<=maxn;++i)
power[i]=power[i-1]*2%mod;
dp[3]=1;
for(int i=4;i<=maxn;++i){
dp[i]+=(i-1)/2-ceil(i/3.0)+1; //b=c:最少时靠近等边三角形,最多时最短边靠近1
dp[i]+=dp[i-1]; //b<c:不考虑c保底的1,(a,b,c)在b<c时的个数=(a,b,c-1)的总个数再减去
//a+b=(c-1)+1时(a,b,c-1)还原后取不到三角形时的个数,因为a+b+c=i,所以化简得c=i/2。
if(i%2==0)
dp[i]=dp[i]-(i/2)/2+mod; //因为a+b已经确定,所以ab的取法只有floor(c/2)
dp[i]%=mod;
}
//枚举最小的三角形的周长可能取值,会发现gcd(a0,b0,c0)=1,因为要保证其它都是它的倍数
//不然的话(6,9,9)不会是(4,6,6)的倍数,而应该是(2,3,3)
//因此,首先要预处理,把dp[]里面那些gcd!=1的情况去掉。这里用了一种类似筛选法的方法。
for(int i=3;i<=maxn;++i){
for(int j=i*2;j<=maxn;j+=i)
dp[j]=(dp[j]-dp[i]+mod)%mod;
}
int n,cnt=0;
while(scanf("%d",&n)!=EOF){
ll s=0;
for(int i=1;i*i<=n;++i){ //枚举最小的单位三角形的周长可能取值
if(n%i==0){
int w=n/i-1; // n/i颗球有n/i-1个缝隙
s=(s+(ll)power[w]*dp[i])%mod; //Cn0-Cn1+Cn2-Cn3+……+(-1)^nCnn=0
if(i*i!=n){
w=i-1;
s=(s+(ll)power[w]*dp[n/i])%mod; //Cn0-Cn1+Cn2-Cn3+……+(-1)^nCnn=0
}
}
}
printf("Case %d: %I64d\n",++cnt,s);
}
return 0;
}