制約より、 を満たす整数値は まで調べればいいです。 というように に値を代入して、 が取りうる値を配列に記録していきます。
の取りうる値ですが、 大きく見積もると
より、 だいたい くらいまでを調べれば良いことが分かります。
の取りうる値は なので、 だいたい くらいです。
( くらいなので、 全捜索しても十分高速に計算できます)
念の為オーバーフローには十分注意してください。
この全捜索における最大値は であるので、
long long 型にしておけば安心です。
を越したら break とか実装すればもっと安心です。
全捜索したあとは配列を昇順にソートし、 重複している項目を削除します。 (実装時には配列を新しく用意しています)
#include <stdio.h>
#include <stdlib.h>
#define ll long long
//比較関数(昇順)
ll cmp(const void* x, const void* y)
{
if (*(ll*)x > * (ll*)y) return 1;
else if (*(ll*)x < *(ll*)y) return -1;
else return 0; // ロイロからコピペしてきた
}
ll pow_(ll a, ll b){
ll ans=1;
for(int i=0; i<b; i++) ans*=a;
return ans;
}
int main(void){
ll l, r; scanf("%lld%lld", &l, &r);
// 全捜索
ll D[4000];
int D_count=0;
for(ll a=4; a<397; a++){
for(ll b=1; b<11; b++){
ll insert = a*(a-1)*(a-2)*(a-3)/24 * pow_(7,b);
if(insert > (ll)1e9) break;
D[D_count] = insert;
D_count++;
}
}
// ソート
qsort(D, D_count, sizeof(ll), cmp);
// 重複を削除
ll E[4000];
E[0] = D[0];
int E_count=1;
for(int i=1; i<D_count; i++){
if(D[i]!=D[i-1]){
E[E_count] = D[i];
E_count++;
}
}
int L=0, R=E_count-1;
while(l>E[L] && L<E_count-1) L++;
while(r<E[R] && 0<R) R--;
printf("%d\n", R-L+1);
}