CON1412 期末考后的休闲比赛[六花的勇者]

感谢Okkkkkkkkk大神的指点!!真心ORZ

博主好久都没有更新了(期末考试蹦蹦蹦!!!差点被劝退竞赛……)然后呢,最近又在刷uscao与LA(英语不及格全靠谷歌翻译……),但是今天偶然在洛谷看见一场比赛,很有趣……于是……邀请竞赛队员(一堆洛谷灰名怒刷4题)

本人认为难度从小到大为3<2<4<1

题目

区间方差

https://www.luogu.org/problem/show?pid=T2005
这里写图片描述
作为代码实现最难题,这道题一开始我使用线段树加快速幂或扩展欧几里得900ms+解决的

/**
 * luogu.org
 * Problem#2005
 * Accepted
 * Time:965ms
 * Memory:18601k
 */
#include<iostream>
#include<fstream>
#include<sstream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cctype>
#include<cmath>
#include<algorithm>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<vector>
using namespace std;
typedef bool boolean;
#define smin(a, b)  (a) = min((a), (b))
#define smax(a, b)  (a) = max((a), (b))
template<typename T>
inline void readInteger(T& u){
    char x;
    int aFlag = 1;
    while(!isdigit((x = getchar())) && x != '-' && x != -1);
    if(x == -1) return;
    if(x == '-'){
        x = getchar();
        aFlag = -1;
    }
    for(u = x - '0'; isdigit((x = getchar())); u = (u << 3) + (u << 1) + x - '0');
    ungetc(x, stdin);
    u *= aFlag;
}

const int moder = 1000000007;

template<typename T1, typename T2>
class Pair{
    public:
        T1 x;
        T2 y;
        Pair(T1 x, T2 y):x(x), y(y){    }
        Pair operator +(Pair another){
            return Pair(x + another.x % moder, y + another.y % moder);
        }
};

typedef class TreeNode{
    public:
        int sum;
        int sum2;
        int from, end;
        TreeNode* left, *right;
        TreeNode(long long sum, int from, int end):from(from), end(end), left(NULL), right(NULL), sum(sum){
            sum2 = sum * sum % moder;
        }
        void pushUp(){
            this->sum = this->left->sum + this->right->sum;
            this->sum %= moder;
            this->sum2 = this->left->sum2 + this->right->sum2;
            this->sum2 %= moder;
        }
}TreeNode;

typedef class SegTree{
    public:
        TreeNode* root;

        SegTree():root(NULL){   }
        SegTree(int size, int* val){
            build(root, 1, size, val);
        }

        void build(TreeNode*& node, int from, int end, int* val){
            node = new TreeNode(0, from, end);
            if(from == end){
                node->sum = val[from];
                node->sum2 = (int)(val[from] * 1LL * val[from] % moder);
                return;
            }
            int mid = (from + end) >> 1;
            build(node->left, from, mid, val);
            build(node->right, mid + 1, end, val);
            node->pushUp();
        }

        void update(TreeNode*& node, int index, int val){
            if(node->from == index && node->end == index){
                node->sum = val;
                node->sum2 = (int)(val * 1LL * val % moder);
                return;
            }
            int mid = (node->from + node->end) >> 1;   
            if(index <= mid)    update(node->left, index, val);
            else update(node->right, index, val);
            node->pushUp();
        }

        Pair<long long, long long> query(TreeNode*& node, int from, int end){
            if(node->from == from && node->end == end){
                return Pair<long long, long long>(node->sum, node->sum2);
            }
            int mid = (node->from + node->end) >> 1;
            if(end <= mid)  return query(node->left, from, end);
            if(from > mid)  return query(node->right, from, end);
            return query(node->left, from, mid) + query(node->right, mid + 1, end);
        }

}SegTree;

/*
int pow_mod(int x, int pos){
    if(pos == 1)    return x;
    int temp = pow_mod(x, pos / 2);
    if(pos & 1) return (int)(temp * 1LL * temp % moder * x % moder);
    return (int)(temp * 1LL * temp % moder);
}
*/

void gcd(int a, int b, int& d, int& x, int& y){
    if(b == 0){
        d = a;x = 1;y= 0;
    }else{  gcd(b, a % b, d, y, x); y -= x * (a / b);   }
}

int getInv(int a, int n){
    int d, x, y;
    gcd(a, n, d, x, y);
    return (x + n) % n;
}

int n, m;
SegTree st;
int* initer;

inline void init(){
    readInteger(n);
    readInteger(m);
    initer = new int[(const int)(n + 1)];
    for(int i = 1; i <= n; i++)
        readInteger(initer[i]);
    st = SegTree(n, initer);
}

inline void solve(){
    int op, a, b;
    while(m--){
        readInteger(op);
        readInteger(a);
        readInteger(b);
        if(op == 1){
            st.update(st.root, a, b);
        }else if(op == 2){
            Pair<long long, long long> p = st.query(st.root, a, b);
            long long L = b - a + 1;
//          long long inv = pow_mod(L * L % moder, moder - 2);
            int inv = getInv(L * L % moder, moder);
            long long fm = (L * (p.y % moder) % moder - p.x * p.x % moder + moder) % moder;
            long long ans = fm * inv % moder;;
            cout << ans << endl;
        }
    }
}

int main(){
    init();
    solve();
    return 0;
}

但是发现出题人有之前的优化方案:
https://www.luogu.org/discuss/show?postid=7330
加上读入优化后达到了500ms+
但是这并不能满足我的野心(优化到第一份代码时间1/2以下),所以……和我厚颜无耻地找出题人要了代码研究(copy……)
其实并没有什么大的改变

#include<cstdio>
typedef long long ll;
const int maxn=100005,mod=1e9+7;
ll rev[maxn],s[maxn],sq[maxn],num[maxn],y,t,ch;
int n,m,c,x,len;
ll Mod(ll x)
{
    while(x>=mod)x-=mod;//就这一处值了200ms+!!!!
    while(x<0)x+=mod;
    return x;
}
void add(ll*b,int p,ll v){for(;p<=n;p+=p&-p)b[p]=Mod(b[p]+v);}
ll ask(ll*b,int p)
{
    ll ans=0;
    for(;p;p-=p&-p)ans=Mod(ans+b[p]);
    return ans;
}
ll ask(ll*b,int x,int y){return ask(b,y)-ask(b,x-1);}
void read(int&x)
{
    x=0,ch=getchar();
    while(ch>'9'||ch<'0')ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
}
void read(ll&x)
{
    x=0,ch=getchar();
    while(ch>'9'||ch<'0')ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
}
int main()
{
    read(n),read(m);
    rev[1]=1;for(register int i=2;i<=n;++i)rev[i]=(mod-mod/i)*rev[mod%i]%mod;
    for(register int i=1;i<=n;++i)read(num[i]),add(s,i,num[i]),add(sq,i,num[i]*num[i]%mod);
    while(m--)
    {
        read(c),read(x),read(y);
        if(c==1)
        {
            add(s,x,Mod(y-num[x]));
            add(sq,x,Mod(y*y%mod-num[x]*num[x]%mod));
            num[x]=y;
        }
        else
        {
            len=y-x+1;t=ask(s,x,y)*rev[len]%mod;
            printf("%lld\n",Mod((rev[len]*ask(sq,x,y)%mod-t*t%mod)));
        }
    }
    return 0;
}

至今原因不明………………

漂浮的鸭子

https://www.luogu.org/problem/show?pid=T2049
这里写图片描述
一开始算法学傻了……就知道Trajan……
所以很慢…………

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<stack>
#define rez(i,x,y) for(int i=x;i>=y;i--)
#define res(i,x,y) for(int i=x;i<=y;i++)
#define INF 2100000000
#define ll long long
#define NAME "scc"
#define clr(x)  memset(x,0,sizeof(x))
#define maxn 1000005
using namespace std;
template <class T>
inline int readin(T &res){
  static char ch;
  while ((ch = getchar()) < '0' || ch > '9');
    res = ch - 48;
  while ((ch = getchar()) >= '0' && ch <= '9')
    res = res * 10 + ch - 48;
}
vector<int> G[maxn];
int pre[maxn],lowlink[maxn],sccon[maxn],num[maxn],val[maxn],b[maxn];
int n,dfs_clock,scc_cnt,total;
stack<int> S;
void dfs(int u){
    pre[u]=lowlink[u]=++dfs_clock;
    S.push(u);
    for(ll i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(!pre[v]){
            dfs(v);
            lowlink[u]=min(lowlink[u],lowlink[v]);
        }else if(!sccon[v]){
            lowlink[u]=min(lowlink[u],pre[v]);
        }
    }
    if(lowlink[u]==pre[u]){
        scc_cnt++;
        while(1){
            ll x=S.top();S.pop();
            sccon[x]=scc_cnt;
            if(x==u)break;
        }
    }
}
void find_scc(int n){
    dfs_clock=scc_cnt=0;
    clr(sccon);
    clr(pre);
    for(ll i=0;i<n;i++){
        if(!pre[i])dfs(i);
    }
}
int main(){
    readin(n);
    for(int y,x,i=1;i<=n;i++){
        readin(x);readin(val[i]);
        G[i].push_back(x);
    }
    find_scc(n);
    for(int i=1;i<=n;i++){
        total=max(total,sccon[i]);
        num[sccon[i]]+=val[i];
        b[sccon[i]]++;
    }
    int ans=0;
    for(int i=1;i<=total;i++){
        if(b[i]>1)ans=max(ans,num[i]);
    }
    cout<<ans<<endl;
    return 0;
}

然后一位刚刚开始学树的同学用搜索…………
快爆了!!!!

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 100000+10;
int n, D[MAXN], T[MAXN], tvolk=0, time[MAXN], volk[MAXN], tim=0;
void search(int volki, int i, int papa)
{
    volk[i]=volki;
    time[i]=time[papa]+T[papa];
    if (!volk[D[i]]) search(volki,D[i],i);
    else if (volk[i]==volk[D[i]])tim=max(tim,time[i]+T[i]-time[D[i]]);
}
int main()
{
    memset(time,0,sizeof(time));
    memset(volk,0,sizeof(volk));
    scanf("%d",&n);
    for (int i=1; i<=n; i++) scanf("%d%d",&D[i],&T[i]);
    for (int i=1; i<=n; i++) if (!volk[i]) search(++tvolk,i,0);
    printf("%d\n",tim);
    return 0;
}

看来NOIP没有得一等奖是有原因的。

最大差值

https://www.luogu.org/problem/show?pid=T2061
这里写图片描述
水水水水水水!!!!

//打擂台思想,贪心
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<stack>
#define rez(i,x,y) for(int i=x;i>=y;i--)
#define res(i,x,y) for(int i=x;i<=y;i++)
#define INF 2100000000
#define ll long long
#define clr(x)  memset(x,0,sizeof(x))

using namespace std;
template <class T> inline void readin(T &xx)
{
    xx = 0;
    T flag = 1;
    char ch = (char)getchar();
    while(ch<'0' || ch>'9')
    {
        if(ch == '-') flag = -1;
        ch = (char)getchar();
    }
    while(ch>='0' && ch<='9')
    {
        xx = (xx<<1) + (xx<<3) + ch - '0';
        ch = (char)getchar();
    }
    xx *= flag;
}
int x,n,minn,tot;
int main(){
    readin(n);
    for(int i=1;i<=n;i++){
        readin(x);
        if(i==1)minn=x;
        else{
            if(x>minn)tot=max(tot,x-minn);
            else minn=x;
        }
    }
    printf("%d\n",tot);
    return 0;
}

随机数生成器

看到题目我就感到了来自数论的不友善的目光…………
惯用手段!!打表万岁
90code

//表的生成器
#include<iostream>
#include<cstdio>
#include<cstdlib>
#define rez(i,x,y) for(int i=x;i>=y;i--)
#define res(i,x,y) for(int i=x;i<=y;i++)
#define INF 2100000000
#define ll long long
#define clr(x)  memset(x,0,sizeof(x))
#define maxn 1000005
using namespace std;
double st=23.063621,p=47326467160.266045,t=47326467160.266045;
int main(){
    //freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    for(ll i=2145000000LL;i<2300000000LL;i++){
        st=(t+i)/(i-1),p+=st,t=p;
        if((i/5000000LL)>439&&i%5000000LL==0){
            printf("else if(x/5000000==%I64d)st=%lf,p=%lf,t=%lf;\n",i/5000000LL,st,p,t);

        }
    }
    return 0;
}

t请自动忽略,纯属脑抽。
不知道为什么T9就是过不去,绝对有毒…………

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<stack>
#define rez(i,x,y) for(int i=x;i>=y;i--)
#define res(i,x,y) for(int i=x;i<=y;i++)
#define INF 2100000000
#define ll long long
#define clr(x)  memset(x,0,sizeof(x))
#define maxn 1000005
using namespace std;
template <class T>
inline int readin(T &res){
  static char ch;
  while ((ch = getchar()) < '0' || ch > '9');
    res = ch - 48;
  while ((ch = getchar()) >= '0' && ch <= '9')
    res = res * 10 + ch - 48;
}
int x;
double st=0,p=0,t=0;
int main(){
    cin>>x;
    if(x/5000000==0){
        for(int i=2;i<=x;i++){
            st=(t+i)/(i-1),p+=st,t=p;
        }
        printf("%0.5lf",st);
        return 0;
    }
    else if(x/5000000==1)st=17.002164,p=80010820.176497,t=80010820.176497;
    else if(x/5000000==2)st=17.695311,p=166953112.658580,t=166953112.658580;
    else if(x/5000000==3)st=18.100776,p=256511645.859481,t=256511645.859481;
    else if(x/5000000==4)st=18.388458,p=347769169.428388,t=347769169.428388;
    else if(x/5000000==5)st=18.611602,p=440290050.693344,t=440290050.693344;
    else if(x/5000000==6)st=18.793924,p=533817707.635781,t=533817707.635781;
    else if(x/5000000==7)st=18.948074,p=628182599.452376,t=628182599.452376;
    else if(x/5000000==8)st=19.081606,p=723264226.579084,t=723264226.579084;
    else if(x/5000000==9)st=19.199389,p=818972491.568537,t=818972491.568537;
    else if(x/5000000==10)st=19.304749,p=915237460.914611,t=915237460.914611;
    else if(x/5000000==11)st=19.400059,p=1012003266.945319,t=1012003266.945319;
    else if(x/5000000==12)st=19.487071,p=1109224246.605193,t=1109224246.605193;
    else if(x/5000000==13)st=19.567113,p=1206862376.529425,t=1206862376.529425;
    else if(x/5000000==14)st=19.641221,p=1304885502.043997,t=1304885502.043997;
    else if(x/5000000==15)st=19.710214,p=1403266074.730120,t=1403266074.730120;
    else if(x/5000000==16)st=19.774753,p=1501980228.103149,t=1501980228.103149;
    else if(x/5000000==17)st=19.835377,p=1601007085.245298,t=1601007085.245298;
    else if(x/5000000==18)st=19.892536,p=1700328229.887734,t=1700328229.887734;
    //******^^^^^^^^23333333333333333333333333333333333完整表就不放完了,明白就好 
    else if(x/5000000==424)st=23.051898,p=46750022890.877975,t=46750022890.877975;
    else if(x/5000000==425)st=23.054253,p=46865288270.431168,t=46865288270.431168;
    else if(x/5000000==426)st=23.056603,p=46980565414.694550,t=46980565414.694550;
    else if(x/5000000==427)st=23.058948,p=47095854296.046997,t=47095854296.046997;
    else if(x/5000000==428)st=23.061287,p=47211154887.035942,t=47211154887.035942;
    else if(x/5000000==429)st=23.063621,p=47326467160.266045,t=47326467160.266045;
    else if(x/5000000==430)st=23.065949,p=47441791111.636383,t=47441791111.636383;
    int sum=(x/5000000)*5000000;
    while(sum<=x){
        ++sum;
        st=(t+sum)/(sum-1),p+=st,t=p;
    }
    printf("%0.5lf",st);
    return 0;
}

打表还是我这个蒟蒻的强项啊!!!
但没有这个式子:st=(p+sum)/(sum-1),p+=st,我也做不出来。
然后我不服……我曾经可是数竞的啊!!!
所以狡诈了一下……

#include <cstdio>
#include <cmath>
int n;
double w=2;
int main(){
    scanf("%d",&n);
    if (n>10000000){
        printf("%0.5lf\n",1.57721566490123286060651209+log(n-1));
        return 0;
    }
    else if (n==1) printf("0.00000");
    else
    {
        for (int i=3; i<=n; i++) w+=1.0/(i-1);
        printf("%0.5lf\n",w);
    }
    return 0;
}
//0.57721566490123286060651209

0.57721566490123286060651209……是什么呢?欧拉常数。
有什么用呢?作用如上。
原理?http://baike.baidu.com/link?url=s-Bo62nMcueyWPeSZumHgR7Y8s3RuPEsbcUyrbkw7ttbNvPv5xA-wj8PwTpdg2ZzEnKp53v5ET74f8Sl89oChFGqbbnDUlzroYF1Rc0GGTTyP5P6B3dZG51FxB325RSM 自己看吧。
好嘞,苟日新,日日新,又日新。
这里写图片描述

#1就是我!!MVP!!。
#2就是无私而又伟大的出题人。
#3#4#10都是我们学校的人。

是不是发现没有每日推荐?恩,的却是这样啊,但是看看图。
那就算了吧。。。。
错了错了
推荐吧
六花的勇者(推理+悬疑,情节波澜起伏,不被剧透的话,很令人震撼)
http://baike.baidu.com/link?url=lnH3BxhkC4O1RMVVjqi5x8nhQrkLwzdSpIQbj2iFNVvbjsB_ebKBeMhiUBDLm2PsOR3xtyFDrEf-XsXLqToZAF5m_rkcvuhNLp5g9qWujhadEz2dGHeiY205JUhwPLdp_hU9kTvJuW8U1U9JVJHqi_
云盘连接:http://pan.baidu.com/s/1kVO9w9p
这里写图片描述
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值