列表

详情


NC22592. 小D的Lemon

描述

あの日の悲しみさえ
那一天的悲伤也好
あの日の苦しみさえ 
那一天的痛苦也好 
そのすべてを愛してた あなたとともに 
我深爱着和你在一起的点点滴滴 
胸に残り離れない 
残留在心中久久不离 
苦いレモンの匂い 
苦柠檬的香气 
雨が降り止むまでは帰れない 
雨停为止都无法回去 
切り分けた果実の片方の様に 
如同切开的果实的一面那样 
今でもあなたはわたしの光 
至今为止你依然是我的光
米津玄师—《Lemon》
题目描述
旧日的美好已如昙花般绽放之后消失的无影无踪,只剩下些许的回忆和无穷的悔恨。如梦般的时光已经逝去,但值得庆幸的是,仍有电脑、鼠标、键盘和那一串串的公式无言却忠诚地记录着过去。
小D在时光的缝隙中找到了一个公式


若把一个正整数  分解为若干质数的乘积,即,定义

公式的结果,是一段小D重要的回忆,因此小D一直在不停寻找着答案。

人脑可真是个不可靠的磁盘呢——无论是记录还是删除。

雨后的空气格外清新,夹杂着柠檬的香气,青涩而又甘甜。小D探索着公式的奥妙,在数学的海洋里找寻着往昔的光芒。

输入描述

第一行为一个整数 T ,表示数据的组数
接下来 T 行,每行两个整数 n, m

输出描述

一共T行,第 i 行输出第 i 组数据的答案,答案对  取模

示例1

输入:

1
4 5

输出:

2

说明:

g(1)=g(2)=g(3)=g(5)=1,g(4)=2
当i=4,j=4时,g(gcd(i,j))=2,其他g(gcd(i,j))=1

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 185ms, 内存消耗: 8596K, 提交时间: 2019-02-15 21:23:39

#include<stdio.h>
#include<algorithm>
#include<math.h>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
int T,n,m,pri[260000],g[260000],pt,mu[260000],j,i,te;
bool isp[260000];
long long f[260000],ans,G[260000],inv[100],pre[260000],ing[260000];
const int p=1e9+7;
inline long long qpow(long long a,long long n){
	if (a==1) return 1;//!!!
	long long s=1;
	while (n){
		if (n&1) s=s*a%p;
		a=a*a%p;
		n>>=1;
	}
	return s;
}
int main(){
	inv[1]=1;
	fo(i,2,100) inv[i]=qpow(i,p-2);
	g[1]=1;G[1]=1;mu[1]=1;
	fo(i,2,250000){
		G[i]=1;
		if (!isp[i]){
			pri[++pt]=i;
			g[i]=1;
			mu[i]=-1;
		}
		fo(j,1,pt){
			te=i*pri[j];
			if (te>250000) break;
			isp[te]=1;
			g[te]=g[i]+1;
			if (i%pri[j]==0) break;//!!!!!
			mu[te]=-mu[i];//!!!!!!!!
		}
	}
	fo(i,1,250000){
		if (mu[i]==1) for(int j=i,k=1;j<=250000;j+=i,k++) G[j]=G[j]*g[k]%p;
		if (mu[i]==-1) for(int j=i,k=1;j<=250000;j+=i,k++) G[j]=G[j]*inv[g[k]]%p; 
	}
	pre[0]=ing[0]=1;
	fo(i,1,250000) pre[i]=pre[i-1]*G[i]%p;
	ing[250000]=qpow(pre[250000],p-2);
	fd(i,249999,1) ing[i]=ing[i+1]*G[i+1]%p;
//	fo(i,1,10) printf("%lld\n",ing[i]*pre[i]%p);
//	printf("%d\n",g[40]);//4
	scanf("%d",&T);
	while (T--){
		scanf("%d%d",&n,&m);
		if (n>m) std::swap(n,m);
//		ans=1;
//		fd(i,n,4){
//			f[i]=(n/i)*1ll*(m/i);
//			for(int j=i+i;j<=n;j+=i) f[i]-=f[j];
//			ans=ans*qpow(g[i],f[i])%p;
//		}
//		printf("%lld\n",ans);
//		ans=1;
//		fo(i,1,n) ans=ans*qpow(G[i],(n/i)*1ll*(m/i))%p;
//		printf("%lld\n",ans);
		ans=1;
		i=1;
		while (i<=n){
			j=std::min(n/(n/i),m/(m/i));
			ans=ans*qpow(pre[j]*ing[i-1]%p,(n/i)*1ll*(m/i))%p;//pre[i]*ing[j-1]!!!!
			i=j+1;
		}
		printf("%lld\n",ans);
	}
	return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 483ms, 内存消耗: 4832K, 提交时间: 2020-03-25 15:22:08

#include<iostream>
#include<cstdio>
const int N=250005;
typedef long long ll;
const ll mod=1e9+7;
ll qpow(ll x,ll y)
{
	ll res=1;
	for(;y;y>>=1,x=x*x%mod)
	if(y&1) res=res*x%mod;
	return res;
}
int u[N],prime[N],cnt,g[N];
bool vis[N];
ll f[N];
void init()
{
	g[1]=1;
	f[1]=1;
	u[1]=1;
	for(int i=2;i<N;i++)
	{
		if(!vis[i])
		u[i]=-1,prime[cnt++]=i,g[i]=1;
		for(int j=0;j<cnt&&i*prime[j]<N;j++)
		{
			vis[i*prime[j]]=1;
			g[i*prime[j]]=g[i]+1;
			if(i%prime[j]==0) break;
			u[i*prime[j]]=-u[i];
		}
		f[i]=1;
	}
	for(int i=1;i<N;i++)
	for(int j=i;j<N;j+=i)
	{
		if(!u[j/i]) continue;
		f[j]=f[j]*(u[j/i]>0?g[i]:qpow(g[i],mod-2))%mod;
	}
	for(int i=2;i<N;i++)
	f[i]=f[i]*f[i-1]%mod;
	f[0]=1;
}
int main()
{
	int T,n,m;
	init();
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m);
		if(n>m) std::swap(n,m);
		ll ans=1;
		for(int i=1,j;i<=n;i=j+1)
		{
			j=std::min(n/(n/i),m/(m/i));
			ans=ans*qpow(f[j]*qpow(f[i-1],mod-2)%mod,1LL*(n/i)*(m/i))%mod;
		}
		printf("%lld\n",ans);
	}
	return 0;
}

上一题