题意:构造f[i][0]=a,f[i][i]=b,f[i][j]=f[i-1][j-1]+f[i-1][j]的30行30列的类杨辉三角矩阵,计算所有的数对有(a,b)中有多少个位置的值等于m。
分析:因为我们的构造方法是一样的,变动的是a和b,那么我们在每一个位置f[i][j]的a的系数A和b的系数B是能预处理出来的,那么对于每一个位置有A*a+B*b,那么我们求解的就是不定方程A*x+B*y=m的正整数的解的个数,用扩展欧几里得算一下就行了。
代码:
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=100010;
const int MAX=1000000100;
const int mod=100000000;
const int MOD1=1000000007;
const int MOD2=1000000009;
const double EPS=0.00000001;
typedef long long ll;
const ll MOD=998244353;
const int INF=1000000010;
typedef double db;
typedef unsigned long long ull;
int a[35][35],b[35][35];
void deal() {
int i,j;
for (i=0;i<=30;i++) a[i][0]=b[i][i]=1;
for (i=2;i<=30;i++)
for (j=1;j<i;j++) {
a[i][j]=a[i-1][j-1]+a[i-1][j];
b[i][j]=b[i-1][j-1]+b[i-1][j];
}
}
int gcd(int a,int b) {
return b ? gcd(b,a%b):a;
}
void ex_gcd(int a,int b,int &x,int &y) {
if (!b) { x=1;y=0; }
else { ex_gcd(b,a%b,y,x);y-=x*(a/b); }
}
int get(int a,int b,int m) {
int g=gcd(a,b),x,y;
if (m%g!=0) return 0;
a/=g;b/=g;m/=g;
ex_gcd(a,b,x,y);
x*=m;y*=m;
if (x<=0) { g=(1-x/b);x+=b*g;y-=a*g; }
if (x>b) { g=(x-1)/b;x-=b*g;y+=a*g; }
if (y>0) return (y+a-1)/a;
return 0;
}
int main()
{
int i,j,t,m;
ll ans;
deal();
scanf("%d", &t);
while (t--) {
scanf("%d", &m);
ans=0;
for (i=2;i<=30;i++)
for (j=1;j<i;j++)
ans+=(ll)get(a[i][j],b[i][j],m);
printf("%lld\n", ans);
}
return 0;
}