• 奇怪的数论


    不想写博客,但是感觉自己又不是很会,只能写上便于自己以后应用了

    P2261余数求和 数论分块

    数论分块的应用:求解关于(leftlfloordfrac{n}{i} ight floor)的求和问题。

    对于任意一个(i)((ileqslant n)),我们需要找到一个最大的(j)((ileqslant jleqslant n))使得 (leftlfloorfrac{n}{i} ight floor) =(leftlfloorfrac{n}{j} ight floor),此时(j)=(leftlfloorfrac{n}{leftlfloorfrac{n}{i} ight floor} ight floor).
    此时我们发现在一段区间内(leftlfloorfrac{n}{i} ight floor),的值是相同的,所以我们用这一段的长度( imes)这一段的值,分块求解。

    int ans=0;
    for(int l = 1,r = 0;l <= n;l=r+1){
        r=n/(n/l);  			// 求区间的右端,这是一个数学规律 
        ans+=(r-l+1)*(n/l);
    } 	
    

    那么对于这道题而言(sumlimits_{i=1}^n{kmodi}),它等价于(sumlimits_{i=1}^n {k-leftlfloordfrac{k}{i} ight floor imes i}),再变形一下就变成了(nk-sumlimits_{i=1}^n {leftlfloordfrac{k}{i} ight floor imes i}),这样求余数和的问题就被我们转化乘求(sumlimits_{i=1}^n {leftlfloordfrac{k}{i} ight floor} imes i)的问题

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    using namespace std;
    long long n,k;
    long long solve(long long n,long long k){
      long long ans=n*k;
      for (long long l=1,r;l <= n;l=r+1){
        if (k/l!=0) r=min(k/(k/l),n);
        else r=n;
        ans-=(k/l)*(r-l+1)*(l+r)/2;//区间长度*区间平均值*向下取整的贡献
      }
      return ans;
    }
    int main(){
      scanf ("%lld%lld",&n,&k);
      long long ans=solve(n,k);
      printf("%lld
    ",ans);
      return 0;
    }
    

    P3708 koishi的数学题 线性筛求约数和

    虽然和第一题长的比较像,但是好像没什么关系,当然还是需要变化式子:
    (sumlimits_{k=1}^n {sumlimits_{i=1}^n {xmodi}}),先看里面的公式,和上一道题完全一样的变形(nx-sumlimits_{i=1}^n {leftlfloordfrac{x}{i} ight floor imes i}),再看外层嵌套的公式,如果我们能推出相邻两个之间的关系,那么我们就可以递推出整个式子.
    (egin{aligned}f(x) & = n imes x-sumlimits_{i=1}^n {leftlfloordfrac{x}{i} ight floor imes i }end{aligned})
    (egin{aligned}f(x+1) & = n imes (x+1) - sumlimits_{i=1}^n {leftlfloordfrac{x +1}{i} ight floor imes i}end{aligned})
    两式相减得到:(egin{aligned}f(x+1)-f(x) & = n-sumlimits_{i=1}^n {left(leftlfloordfrac{x+1}{i} ight floor-leftlfloordfrac{x}{i} ight floor ight)}end{aligned})
    对于最后一个式子,明显只有当(i|(x+1))的时候,(leftlfloordfrac{x+1}{i} ight floor-leftlfloordfrac{x}{i} ight floor = 1),否则为0
    因此只有(i)(x+1)的因数时,才会对答案有贡献,所以对于做外层的(k)来说,答案就是(k)的因数和,线性筛求因数和这东西就……先背下来吧。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #define int long long 
    using namespace std;
    const int maxn=1e6+10;
    int n,tot;
    int g[maxn],f[maxn],primelist[maxn],dp[maxn],vis[maxn];
    void init(){
      g[1]=f[1]=1;
      for (int i = 2;i <= n;i++){
        if (!vis[i]) vis[i]=1,primelist[++tot]=i,g[i]=f[i]=i+1;
        for (int j = 1;j <= tot&&i*primelist[j]<=n;j++){
          vis[primelist[j]*i]=1;
          if (i%primelist[j]==0){
    	g[i*primelist[j]]=g[i]*primelist[j]+1;
    	f[i*primelist[j]]=f[i]/g[i]*g[i*primelist[j]];
    	break;
          }
          else{
    	f[i*primelist[j]]=f[i]*f[primelist[j]];
    	g[i*primelist[j]]=1+primelist[j];
          }
        }
      }
      // for (int i = 1;i <= n;i++) f[i]=f[i-1]+f[i];
    }
    signed main(){
      scanf ("%lld",&n);
      init();
      for (int i = 1;i <= n;i++) dp[i]=dp[i-1]+n-f[i];
      for (int i = 1;i <= n;i++) printf("%lld ",dp[i]);
      return 0;
    }
    

    P1544 蜈蚣 前缀异或和

    dp外加前缀异或和,和前缀和差不多,记一下就好了

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    ll a[1000005],ans[1000005];
    int n,m;
    int main(){
      cin>>n;
      for(int i = 1; i<=n; i++) {
        scanf("%lld",&a[i]);
        ans[i] = ans[i-1] ^ a[i];
      }
      int l,r;
      while(m--) {
        scanf("%d%d",&l,&r);
        printf("%lld
    ",ans[r] ^ ans[l - 1]);
      }
      return 0;
    } 
    
  • 相关阅读:
    4-数组、指针与字符串1.3-this指针
    Linux命令----cp
    Linux命令----mv
    Linux命令----rm
    PHP7下的协程实现 转
    php生成器 yield 转
    python并发编程之多进程(实践篇) 转
    python 多进程
    线程创建 线程数
    多任务 执行
  • 原文地址:https://www.cnblogs.com/very-beginning/p/13803710.html
Copyright © 2020-2023  润新知