1. 程式人生 > >貝殼找房算數(中等)

貝殼找房算數(中等)

描述

貝殼找房力求為每位使用者找到滿意的房子,最近貝殼找房通過大資料得出下面的一個結論,
求滿足0<i,j<=n,f(i) * f(j)>0,且0 < gcd(f(i),f(j)) <= k的數對 (i,j)的數量,其中滿足條件的對數就是可以滿足某位使用者的房源數目。
其中 f(x)表示 x 所有數位的積,比如 f(124)=1 * 2 * 4 = 8.
因答案很大,請求出其在模 998244353意義下的結果。其中 gcd(x, y)表示x和y的最大公約數。
提示: 其中 (1,2), (2,1)算是兩種情況。

輸入格式

一行兩個正整數,分別表示 n和k。
保證1<=n<=1e6,1<=k<=1e18。

輸出格式

一個整數表示答案。

樣例輸入

9 5

樣例輸出

77

思路

對於數位積相同的可以只算一次,用map存起來個數,這樣就可以將複雜度壓下來了。

程式碼

#include<bits/stdc++.h>
#pragma warning(disable:4786)
#define ll long long 
using namespace std;  

inline ll hh(ll i){  //求數位積
    ll temp=1ll;  
    while(i){
        temp*=(i%10);  
        i/=10;  
    }
    return temp;
} 
int main(){
    //freopen("2.txt", "r", stdin);  
    ll n, k;  
    scanf("%lld%lld", &n, &k);  
    ll ans =0;  
    map<ll,ll>mp;  
    map<ll,ll>::iterator it1,it2;  
    for(ll i=1;i<=n;i++){  //一個個的求出數位積,放到map裡
        ll temp=hh(i);  
        if(temp!=0)mp[temp]++;  
    }
    for(it1=mp.begin();it1!=mp.end();it1++){  //對於數位積,來個二重迴圈計算
        for(it2=it1;it2!=mp.end();it2++){
            if(__gcd((*it1).first,(*it2).first)<=k){  //通過algorithm裡面的__gcd直接求公約數
                ll temp=(*it1).second * (*it2).second ;  
                ans +=temp;  
                ans %= 998244353;
                if(it1 != it2)ans +=temp;  //不是一樣的,算兩次
                ans %= 998244353;
            }
        }
    }
    printf("%lld\n",ans);  
}