莫反做题记
给定函数
则有:
[POI2007] ZAP-Queries
即:
点击查看代码
#define yhl 0
#include<bits/stdc++.h>
using namespace std;
const int N=5e4+100;
int miu[N],prime[N],tot,t,n,m,d;
bool vis[N];
void get_miu(){
miu[1]=1;vis[1]=1;
for(int i=2;i<N;i++){
if(!vis[i])prime[++tot]=i,miu[i]=-1;
for(int j=1;j<=tot&&i*prime[j]<N;j++){
vis[i*prime[j]]=1;
if(i%prime[j])miu[i*prime[j]]=-miu[i];
else{
miu[i*prime[j]]=yhl;break;
}
}
}
for(int i=1;i<N;i++)miu[i]+=miu[i-1];
}
int ghfz(int n,int m){
int ans=yhl,r=yhl;
for(int i=1;i<=n;i=r+1){
r=min(n/(n/i),m/(m/i));
ans+=(miu[r]-miu[i-1])*(n/i)*(m/i);
}
return ans;
}
int main(){
get_miu();
scanf("%d",&t);
while(t--){
scanf("%d%d%d",&n,&m,&d);
n/=d,m/=d;if(m<n)swap(n,m);
printf("%d\n",ghfz(n,m));
}
return yhl;
}
YY的GCD
点击查看代码
#define yhl 0
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e7+100;
int miu[N],prime[N],tot,t,n,m,d,f[N],s[N];
bool vis[N];
void get_miu(){
miu[1]=1;vis[1]=1;
for(int i=2;i<N;i++){
if(!vis[i])prime[++tot]=i,miu[i]=-1;
for(int j=1;j<=tot&&i*prime[j]<N;j++){
vis[i*prime[j]]=1;
if(i%prime[j])miu[i*prime[j]]=-miu[i];
else{miu[i*prime[j]]=yhl;break;}
}
}
for(int i=1;i<=tot;i++)
for(int j=1;j*prime[i]<N;j++)
f[j*prime[i]]+=miu[j];
for(int i=1;i<N;i++)s[i]=s[i-1]+f[i];
}
int ghfz(int n,int m){
int ans=yhl,r=yhl;
for(int i=1;i<=n;i=r+1){
r=min(n/(n/i),m/(m/i));
ans+=(s[r]-s[i-1])*(n/i)*(m/i);
}
return ans;
}
signed main(){
get_miu();
scanf("%lld",&t);
while(t--){
scanf("%lld%lld",&n,&m);
if(m<n)swap(n,m);
printf("%lld\n",ghfz(n,m));
}
return yhl;
}
[SDOI2015] 约数个数和
点击查看代码
#define yhl 0
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=5e4+100;
int miu[N],prime[N],tot,t,n,m,d,f[N];
bool vis[N];
void get_miu(){
miu[1]=1;vis[1]=1;
for(int i=2;i<N;i++){
if(!vis[i])prime[++tot]=i,miu[i]=-1;
for(int j=1;j<=tot&&i*prime[j]<N;j++){
vis[i*prime[j]]=1;
if(i%prime[j])miu[i*prime[j]]=-miu[i];
else{miu[i*prime[j]]=yhl;break;}
}
}
for(int i=1;i<N;i++){
int ans=0,r=0;
for(int j=1;j<=i;j=r+1){
r=(i/(i/j));
ans+=(r-j+1)*(i/j);
}
f[i]=ans;
}
for(int i=1;i<N;i++)miu[i]+=miu[i-1];
}
int ghfz(int n,int m){
int ans=yhl,r=yhl;
for(int i=1;i<=n;i=r+1){
r=min(n/(n/i),m/(m/i));
ans+=(miu[r]-miu[i-1])*f[n/i]*f[m/i];
}
return ans;
}
signed main(){
get_miu();
scanf("%lld",&t);
while(t--){
scanf("%lld%lld",&n,&m);
if(m<n)swap(n,m);
printf("%lld\n",ghfz(n,m));
}
return yhl;
}
[SDOI2017] 数字表格
点击查看代码
#define yhl 0
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+10,p=1e9+7;
int f[N],g[N],n,t,m,prime[N],miu[N],F[N];
bool vis[N];
inline int qum(int a,int b){
int ans=1;
while(b){
if(b&1)ans=1ll*ans*a%p;
a=1ll*a*a%p;
b>>=1;
}
return ans;
}
void init(){
f[1]=g[1]=F[yhl]=F[1]=1;
for(int i=2;i<N;i++)f[i]=(f[i-1]+f[i-2])%p;
vis[1]=1;miu[1]=1;
for(int i=2;i<N;i++){
g[i]=qum(f[i],p-2);F[i]=1;
if(!vis[i])prime[++prime[yhl]]=i,miu[i]=-1;
for(int j=1;j<=prime[yhl]&&i*prime[j]<N;j++){
vis[i*prime[j]]=1;
if(i%prime[j])miu[i*prime[j]]=-miu[i];
else{miu[i*prime[j]]=yhl;break;}
}
}
for(int i=1;i<N;i++){
if(!miu[i])continue;
for(int j=i;j<N;j+=i){
F[j]=1ll*F[j]*(miu[i]==1?f[j/i]:g[j/i])%p;
}
}
for(int i=2;i<N;i++)F[i]=1ll*F[i]*F[i-1]%p;
}
int ghfz(int n,int m){
int ans=1,r=yhl;
for(int i=1;i<=n;i=r+1){
r=min(n/(n/i),m/(m/i));
int ny=1ll*F[r]*qum(F[i-1],p-2)%p;
//注意用逆元来实现前缀积。
ans=1ll*ans*qum(ny,1ll*(n/i)*(m/i)%(p-1))%p;
//这里用费马小定理省去一些不必要的计算。
}
return ans;
}
signed main(){
init();
scanf("%lld",&t);
while(t--){
scanf("%lld%lld",&n,&m);
if(n>m)swap(n,m);
printf("%lld\n",ghfz(n,m));
}
return yhl;
}
数表
点击查看代码
#define yhl 0
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+10,M=1e4+10,p=(1ll<<31);
struct stu{
int n,m,a,id;
bool operator<(const stu stu1)const{
return a<stu1.a;
}
}s[N];
struct sta{
int m,id;
bool operator<(const sta stu1)const{
return m<stu1.m;
}
}di[N];
inline int lb(int x){return x&-x;}
int miu[N],t,prime[N],dd[N],ans[N],c[N];
bool vis[N];
void init(){
vis[1]=1;miu[1]=1;
for(int i=2;i<N;i++){
if(!vis[i]){
prime[++prime[yhl]]=i;
miu[i]=-1;
}
for(int j=1;j<=prime[yhl]&&i*prime[j]<N;j++){
vis[i*prime[j]]=1;
if(i%prime[j])miu[i*prime[j]]=-miu[i];
else break;
}
}
for(int i=1;i<N;i++)
for(int j=i;j<N;j+=i)dd[j]+=i;
for(int i=1;i<N;i++)di[i].id=i,di[i].m=dd[i];
sort(di+1,di+N);
}
void add(int x,int val){
while(x<N){
c[x]=(c[x]+val)%p;
x+=lb(x);
}
}
int get_sum(int x){
int ans=yhl;
while(x){
ans=(ans+c[x])%p;
x-=lb(x);
}
return ans;
}
void Add(int x){
for(int i=1;i*x<N;i++)add(i*x,miu[i]*dd[x]%p);
}
int ghfz(int n,int m){
if(n>m)swap(n,m);
int ans=yhl,r=yhl;
for(int i=1;i<=n;i=r+1){
r=min(n/(n/i),m/(m/i));
ans=(1ll*(1ll*(n/i)*(m/i)%p)*(get_sum(r)-get_sum(i-1)+p)%p+ans)%p;
}
return ans;
}
signed main(){
scanf("%lld",&t);
for(int i=1;i<=t;i++)scanf("%lld%lld%lld",&s[i].n,&s[i].m,&s[i].a),s[i].id=i;
sort(s+1,s+1+t);
int r=yhl;init();
for(int i=1;i<=t;i++){
while(di[r+1].m<=s[i].a&&r<N-1)++r,Add(di[r].id);
ans[s[i].id]=ghfz(s[i].n,s[i].m)%p;
}
for(int i=1;i<=t;i++)printf("%lld\n",ans[i]);
return yhl;
}
P6156 简单题
upd:学长好像已经算出我的时间复杂度为
点击查看代码
#define yhl 0
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define it int
const int N=5e6+100,p=998244353;
int n,k,g[N],s[N<<1],op[N];
it prime[4900000],miu[N];
bool vis[N<<1];
inline int qum(register int a,register int b){
register int ans=1;
while(b){
(b&1)&&(ans=1ll*ans*a%p);
a=1ll*a*a%p;
b>>=1;
}
return ans;
}
inline void init(){
vis[1]=1;miu[1]=1;s[1]=1;
for(register int i=2;i<=n*2;i++){
if(!vis[i]){
if(i<=n)miu[i]=-1;
prime[++prime[yhl]]=i,s[i]=qum(i,k);
}
for(register int j=1;j<=prime[yhl]&&i*prime[j]<=2*n;j++){
vis[i*prime[j]]=1;s[i*prime[j]]=1ll*s[i]*s[prime[j]]%p;
if(i%prime[j])if(i*prime[j]<=n)miu[i*prime[j]]=-miu[i];
else break;
}
}
for( int i=1;i<=n*2;i++)s[i]=(s[i]+s[i-1])%p;
for(register int i=1;i<=n;i++){
g[i]=miu[i]?(g[i-1]+1ll*(s[i]-s[i-1]+p)*i%p)%p:g[i-1];
}
for(register int i=1;i<=n;i++)op[i]=(op[i-1]+(s[i*2]+s[i*2-1]-2*s[i])+p)%p;
register int last=yhl,llst=yhl;
for(register int i=1;i<=n;i++){
llst=last;
last=s[i];
s[i]=(s[i-1]+miu[i]*(s[i]-llst))%p;
if(s[i]<0)s[i]+=p;
}
}
inline int Ghfz(register int n){
register int ans=yhl,r=yhl;
for(register int i=1;i<=n;i=r+1){
r=n/(n/i);
ans+=1ll*(s[r]-s[i-1]+p)*op[n/i]%p;
}
return ans%p;
}
inline int ghfz(register int n){
register int ans=yhl,r=yhl;
for(register int i=1;i<=n;i=r+1){
r=n/(n/i);
register int ret=Ghfz(n/i);
ans+=1ll*(g[r]-g[i-1]+p)*ret%p;
}
return ans%p;
}
signed main(){
scanf("%lld%lld",&n,&k);k%=(p-1);
init();
printf("%lld",ghfz(n));
return yhl;
}
点击查看代码
#define yhl 0
#include<bits/stdc++.h>
using namespace std;
const int N=1e7+10;
#define int unsigned int
int prime[N<<1],f[N],n,t,k,g[N<<1],op[N];
bool vis[N<<1];
int qum(int a,int b){
int ans=1;
while(b){
if(b&1)ans=ans*a;
a=a*a;
b>>=1;
}
return ans;
}
void init(){
vis[1]=1;g[1]=1;f[1]=1;
for(int i=2;i<=2*n;i++){
if(!vis[i]){
prime[++prime[yhl]]=i;g[i]=qum(i,k);
if(i<=n)f[i]=i-1;
}
for(int j=1;j<=prime[yhl]&&i*prime[j]<=2*n;j++){
vis[i*prime[j]]=1;g[i*prime[j]]=g[i]*g[prime[j]];
if(i%prime[j]==yhl){
if(i*prime[j]<=n)
if((i/prime[j])%prime[j])f[i*prime[j]]=-prime[j]*f[i/prime[j]];
break;
}
if(i*prime[j]<=n)f[i*prime[j]]=f[i]*(prime[j]-1);
}
}
for(int i=1;i<=n;i++)f[i]=(f[i-1]+f[i]*g[i]);
for(int i=1;i<=n*2;i++)g[i]+=g[i-1];
for(int i=1;i<=n;i++)
op[i]=(op[i-1]+2*(g[i*2]-g[i])-(g[i*2]-g[i*2-1]));
}
int read(){
int ans=0;char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
void w(int x){
if(x>9)w(x/10);
putchar(x%10+48);
}
signed main(){
t=read(),n=read(),k=read();
init();
while(t--){
n=read();
int ans=yhl,r;
for(int i=1;i<=n;i=r+1){
r=n/(n/i);
ans=(ans+1ll*op[n/i]*(f[r]-f[i-1]));
}
w(ans);puts("");
}
return yhl;
}
Crash的数字表格 / JZPTAB
点击查看代码
#define yhl 0
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e7+10,p=1e8+9;
int prime[N],miu[N],n,t,m,f[N],calc[N];
bool vis[N];
inline int read(){
register int ans=0;char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
inline void w(register int x){
if(x>9)w(x/10);
putchar(x%10+48);
}
inline void init(){
vis[1]=1;miu[1]=1;
for(register int i=2;i<N;i++){
if(!vis[i]){
prime[++prime[yhl]]=i;
miu[i]=-1;
}
for(register int j=1;j<=prime[yhl]&&i*prime[j]<N;j++){
vis[i*prime[j]]=1;
if(!(i%prime[j]))break;
miu[i*prime[j]]=-miu[i];
}
}
for(register int d=1;d<N;d++){
for(register int j=1;j*d<N;j++){
if(miu[d])f[d*j]=(f[d*j]+1ll*(1ll*((1ll*miu[d]*d%p)+p)*d%p)*j%p)%p;
}
}
for(register int i=1;i<N;i++)f[i]=(f[i]+f[i-1])%p;
for(register int i=1;i<N;i++)calc[i]=(calc[i-1]+i)%p;
//这个其实没必要预处理。
}
signed main(){
init();
scanf("%lld",&t);
while(t--){
scanf("%lld%lld",&n,&m);
if(n>m)swap(n,m);
int ans=yhl,r=yhl;
for(register int i=1;i<=n;i=r+1){
r=min(m/(m/i),n/(n/i));
ans=(ans+1ll*(1ll*(f[r]-f[i-1]+p)*calc[n/i]%p)*calc[m/i]%p)%p;
}
w(ans);puts("");
}
return yhl;
}
镜中的野兽
那么
然后还有两个柿子:
证明
然后就有:
整理可得:
所以:
点击查看代码
#define yhl 0
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+10;
int n,m,p,ans;
int ny[N],fact[N];
unordered_map<int,int>d,miu;
inline int C(int n,int m){if(n<m)return 0;return fact[n]*ny[m]%p*ny[n-m]%p;}
int qum(int a,int b){
int ans=1;
while(b){
(b&1)&&(ans=ans*a%p);
a=a*a%p;
b>>=1;
}
return ans;
}
void init(){
fact[yhl]=1;ny[yhl]=1;
for(int i=1;i<N;i++){
fact[i]=fact[i-1]*i%p;
}
ny[N-1]=qum(fact[N-1],p-2);
for(int i=N-2;i;i--){
ny[i]=ny[i+1]*(i+1)%p;
}
}
int get_d(int x){
if(d[x])return d[x];
int tot=yhl;
for(int i=1;i*i<=x;i++){
if(!(x%i))
tot+=1+(i*i!=x);
}
return d[x]=tot;
}
int get_miu(int x){
if(miu[x])return miu[x]-2;
int tot=(x!=1),op=x;
for(int i=2;i*i<=x;i++){
if(!(x%i)){
tot++;
x/=i;
if(x%i==yhl){
miu[op]=2;
return yhl;
}
}
}
miu[op]=(tot&1)?-1:1;
miu[op]+=2;
return (tot&1)?-1:1;
}
int get_g(int x){
int tot=yhl;
for(int i=1;i*i<=x;i++){
if(x%i==yhl){
int j=x/i;
if(get_miu(j))tot=(tot+get_miu(j)*C(get_d(i),n)+p)%p;
if(j!=i&&(get_miu(i)))tot=(tot+get_miu(i)*C(get_d(j),n)+p)%p;
}
}
return tot;
}
int get_f(int x){
int tot=yhl;
for(int i=1;i*i<=x;i++){
if(x%i==yhl){
int j=x/i;
if(get_miu(j))tot=(tot+get_miu(j)*get_g(i)+p)%p;
if(j!=i&&get_miu(i))tot=(tot+get_miu(i)*get_g(j)+p)%p;
}
}
return tot;
}
signed main(){
// freopen("1.in","r",stdin);
scanf("%lld%lld%lld",&n,&m,&p);
init();
for(int i=1;i*i<=m;i++){
if(m%i==yhl){
int j=m/i;
ans=(ans+get_f(j-1))%p;
if(j!=i)ans=(ans+get_f(i-1))%p;
}
}
printf("%lld",ans);
return yhl;
}
《感谢ppllxx_9G的指正🌚》
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· .NET Core 中如何实现缓存的预热?
· 三行代码完成国际化适配,妙~啊~
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?