某谷 P5153 简单的函数
个人感觉这个题可以被打表随便艹过,当然我不是这么做的。。。
虽然n可达10^18,但随便分析一下就可以发现f(n)是极小的,因为f(n)一步就可以跳到f(前100),不信你算一下前100个数的最小公倍数。。
所以可以暴力算出前100个数的f()之后直接用贡献乘起来就行了,不过还有一些小细节。
#include<bits/stdc++.h> #define ll long long using namespace std; const int ha=1000000007,N=105,mi=ha-1; const ll inf=1e18; inline int ksm(int x,int y){ int an=1; for(;y;y>>=1,x=x*(ll)x%ha) if(y&1) an=an*(ll)x%ha; return an; } ll gcd(ll x,ll y){ return y==0?x:gcd(y,x%y);} int f[N],ans=1; ll n,now=1,nxt; inline void init(){ f[2]=1; for(int i=3;i<=100;i++) for(int j=2;;j++) if(i%j){ f[i]=f[j]+1; break;} } inline void solve(){ for(int i=2,d;nxt<=inf;now=nxt,i++){ d=gcd(now,i); if(n/((ll)i/d)<now) nxt=inf+1; else nxt=now/d*(ll)i; ans=ans*(ll)ksm(f[i]+1,(n/now-n/nxt-(now<i?1:0))%mi)%ha; } } int main(){ init(); scanf("%lld",&n); solve(); printf("%d\n",ans); return 0; }
我爱学习,学习使我快乐