某谷 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
",ans);
	return 0;
}

  

原文地址:https://www.cnblogs.com/JYYHH/p/10297262.html