LightOJ

Stella981
• 阅读 587

打表或者画个图可以看出i>根号n时每个i的贡献值相差很小,可以利用公式优化(函数C) 但是注意不能一整段使用公式,否则复杂度还是会劣化到O(n)(显然对gongxian只能逐步递减) 网上看了不少代码,但是都没有对贡献值边界问题给定明确的判断 所以还是加多一个while循环确定贡献值的开端是前面的n/i没有的

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+11;
typedef long long ll;
ll H(ll n,ll j){
    ll ans=0;
    for(int i = 1; i <= j; i++) ans+=n/i;
    return ans;
}
ll C(ll n,ll gongxian){
    return gongxian*(n/gongxian-n/(gongxian+1));
}
int main(){
    int T,kase=0; scanf("%d",&T);
    while(T--){
        ll n; scanf("%lld",&n);
        if(n<=20){
            printf("Case %d: %lld\n",++kase,H(n,n));
            continue;
        }
        ll gen = sqrt(n);
        ll ans1 = H(n,gen);
        ll tmp = n/gen;
        ll cnt=gen;
        while(1){
            if(n/gen==n/(cnt+1)){
                ans1+=n/gen;
                cnt++;
            }
            else{
                cnt++;//start
                break;
            }
        }
        ll gongxian = n/cnt;
        ll ans2=0;
        while(gongxian){
            ans2+=C(n,gongxian);
            gongxian--;
        }
        printf("Case %d: %lld\n",++kase,ans1+ans2);
    }
    return 0;
}

顺便附加对规律观察用的代码

#include<bits/stdc++.h>
#define rep(i,j,k) for(int i = j; i <= k; i++)
#define scan(a) scanf("%d",&a)
using namespace std;
typedef pair<int,int> P;
const int maxn = 1e6+11;
typedef long long ll;
int cnt[maxn],n;
bool C(int n){
    memset(cnt,0,sizeof cnt);
    rep(i,1,n) cnt[n/i]++;
    int maxzero=0,num=0;
    rep(i,1,n) if(i>=sqrt(n)&&cnt[i]==1) num++;
    // cout<<(int)sqrt(n+0.5)+1<<" "<<cnt[(int)sqrt(n+0.5)+1]<<endl;
    // return cnt[(int)sqrt(n+0.5)+1];
    cout<<num<<endl;
}
int main(){
    // rep(i,1,10000) if(C(i)) cout<<i<<endl;
    srand(time(NULL));
    int n=rand()%1000000;
    C(n);cout<<sqrt(n)<<endl;
}

可以看出[根号n,n]对答案的贡献基本等于根号n

#include<bits/stdc++.h>
using namespace std;
int main(){
    int cnt=0;
    for(int i = 100; i <= 1e6; i++){
        int a=i/(int)sqrt(i),b=sqrt(i);
        if(a-b<0) cnt++;
        // cout<<i<<" "<<a-b<<endl;
        
    }
    cout<<cnt<<endl;
}

可以看出a(应该)都是大于等于b 待做同类题目:1257 2956

//BACKUP
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+11;
typedef long long ll;
ll cal(int n,int k){
    ll ans=0;
    for(int i = 1; i <= n; i++) ans+=k%i;//k-(k/i)*i
    return ans; 
}
ll G(int n,int k){
    ll ans=0;
    for(int i = 1; i <= n; i++) ans+=(k/i)*i;
    return ans; 
}
ll con(ll k,ll i){return i*(k/i-k/(i+1));}
ll sum(ll a1,ll n,ll d){return a1+(n-1)*d;}
int main(){
    int n,k;
    while(cin>>n>>k){
        if(n<=100){
            cout<<cal(n,k)<<endl;
            continue;
        }
        ll root=sqrt(n);
//        cout<<"root"<<root<<endl;
        ll ans1=1ll*k*n;
        ll ans2=G(root,k); //
        ll ans3=0;
        int cnt=root+1;
        
        if(k/cnt==0){//防止越界处理 
            cout<<ans1-G(root,k)<<endl;
            continue;
        }
        while(1){
            if(k/root==k/(cnt+1)){
                ans3+=(k/(cnt+1))*(cnt+1);
                cnt++;
//                cout<<k/root<<" "<<k/cnt<<endl;
            }
            else{
                cnt++;
                break;
            }
        }
        bool flag=0;
        ll lim=k/n; if(lim==0) lim++; 
        ll val=k/cnt; if(val==0) flag=1;
        ll now=cnt;
        ll ans4=0;
        while(!flag&&val>=lim){
            cout<<"NOW "<<now<<endl;
            ll LEN = k/val-k/(val+1);
            cout<<"LEN "<<LEN<<endl;
            cout<<"VAL "<<val<<endl;
            ans4+=con(k,val)*(LEN?sum(now,LEN,1):0);
            now+=LEN;
            val--;
        }
        cout<<ans1-(ans2-ans3-ans4)<<endl;
    }
    return 0;
}
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
这些JS工具函数够你用到2020年底了
前言活不多说,自己平时搜集的干货函数奉上。干货函数找出数字在数组中下一个相邻的元素let i  "";let rr  ;const name  (n, arr1)    let num  Number(n);    for (let i  0; i < arr1.length; i)         const elemen
Peter20 Peter20
3年前
mysql中like用法
like的通配符有两种%(百分号):代表零个、一个或者多个字符。\(下划线):代表一个数字或者字符。1\.name以"李"开头wherenamelike'李%'2\.name中包含"云",“云”可以在任何位置wherenamelike'%云%'3\.第二个和第三个字符是0的值wheresalarylike'\00%'4\
Stella981 Stella981
3年前
JS 对象数组Array 根据对象object key的值排序sort,很风骚哦
有个js对象数组varary\{id:1,name:"b"},{id:2,name:"b"}\需求是根据name或者id的值来排序,这里有个风骚的函数函数定义:function keysrt(key,desc) {  return function(a,b){    return desc ? ~~(ak
Stella981 Stella981
3年前
HIVE 时间操作函数
日期函数UNIX时间戳转日期函数: from\_unixtime语法:   from\_unixtime(bigint unixtime\, string format\)返回值: string说明: 转化UNIX时间戳(从19700101 00:00:00 UTC到指定时间的秒数)到当前时区的时间格式举例:hive   selec
Stella981 Stella981
3年前
LeetCode 5561. 获取生成数组中的最大值
文章目录1\.题目2\.解题1\.题目给你一个整数n。按下述规则生成一个长度为n1的数组nums:nums00nums11当2<2i<n时,nums2inumsi
Wesley13 Wesley13
3年前
67,盛最多水的容器
给定 _n_ 个非负整数 _a_1,_a_2,...,_a_n,每个数代表坐标中的一个点 (_i_, _ai_)。在坐标内画 _n_ 条垂直线,垂直线 _i_ 的两个端点分别为 (_i_, _ai_)和(_i_,0)。找出其中的两条线,使得它们与 _x_ 轴共同构成的容器可以容纳最多的水。说明:你不能倾斜容器,且 _n_ 的值至少为2。!
小万哥 小万哥
1年前
Python 循环
Python有两个基本的循环命令:while循环for循环while循环使用while循环,我们可以在条件为真的情况下执行一组语句。示例,打印i,只要i小于6:pythoni1whilei<6:print(i)i1注意:记得增加i的值,否则循环将永远继续