“字节跳动-文远知行杯”广东工业大学第十四届程序设计竞赛


layout: post
title: “字节跳动-文远知行杯”广东工业大学第十四届程序设计竞赛
author: "luowentaoaa"
catalog: true
mathjax: true
tags:

  • 数学
  • 矩阵快速幂
  • 权值线段树

hzy 和zsl 的生存挑战 (签到)

我还是要吐槽一下,题目都说了两人没有交流还怎么能推出一个人相同一个人不相同,如果两个人都相同呢?

puts("1.00\n1.00\n1.00\n1.00");
    return 0;
}

人类史上最大最好的希望事件 (矩阵快速幂求fib前缀平方和)

思路

斐波那契数列前n项和答案为\(F_{N}*F_{N+1}\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pp pair<int,int>
const ll mod=192600817;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;

ll x,y;
typedef vector<ll>vec;
typedef vector<vec>mat;
mat mul(mat& A,mat &B){
    mat C(A.size(),vec(B[0].size()));
    for(int i=0;i<A.size();i++)
        for(int k=0;k<B.size();k++)
        if(A[i][k])
            for(int j=0;j<B[0].size();j++)
            C[i][j]=(C[i][j]+A[i][k]*B[k][j]%mod+mod)%mod;
    return C;
}
mat Pow(mat A,ll n){
    mat B(A.size(),vec(A.size()));
    for(int i=0;i<A.size();i++)B[i][i]=1;
    for(;n;n>>=1,A=mul(A,A))
        if(n&1)B=mul(B,A);
    return B;
}
int main(){
    int q;
    while(~scanf("%d",&q)){
        for(int i=1;i<=q;i++){
            ll a,b,c,d;
            scanf("%lld %lld %lld %lld",&a,&b,&c,&d);
            a=a*4+b+1;b=c*4+d+1;
            if(a>b)swap(a,b);
            a--;
            mat A(2,vec(2)),B(2,vec(2)),F1(2,vec(1)),F2(2,vec(1));
            A[0][0]=A[0][1]=A[1][0]=1;A[1][1]=0;
            F1[0][0]=1;F1[1][0]=0;
            B[0][0]=B[0][1]=B[1][0]=1;B[1][1]=0;
            F2[0][0]=1;F2[1][0]=0;
            A=Pow(A,a);
            B=Pow(B,b);
            F1=mul(A,F1);
            F2=mul(B,F2);
            ll ans1=F1[0][0]*F1[1][0]%mod;
            ll ans2=F2[0][0]*F2[1][0]%mod;
            printf("%lld\n",(ans2-ans1+mod)%mod);
        }
    }
    return 0;
}

超级无敌简单题 (规律)

思路

发现如果出现4就会出现死循环

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll mod=1e8+7;
const int maxn=5e5+50;
const int inf=1e8;
vector<int>ve;
bool isok(int n){
    while(n!=1&&n!=4){
        ll sum=0;
        while(n){
            sum+=(n%10)*(n%10);
            n/=10;
        }
        n=sum;
    }
    return n==1;
}
int main()
{
    int q;
    for(int i=1;i<1100000;i++){
        if(isok(i))ve.push_back(i);
    }
    //cout<<ve.size()<<endl;
    /*for(int i=0;i<ve.size();i++){
        cout<<ve[i]<<endl;
    }*/
    scanf("%d",&q);
    while(q--){
        int n;
        scanf("%d",&n);
        printf("%d\n",ve[n-1]);
    }
    return 0;
}

免费送气球 (权值线段树)

思路

对于每个数存一个数量和val 然后判断数量是否大于查询数量,

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf=1e16;
const ll mod=1e9+7;
const int maxn=1e5+50;

ll sum[maxn*40],val[maxn*40];
int ls[maxn*40],rs[maxn*40];
int cnt;
void update(int &o,int l,int r,int k,int num){
    if(!o)o=++cnt;
    sum[o]+=k;
    val[o]+=1LL*k*num;
    val[o]%=mod;
    if(l==r)return;
    int mid=(l+r)/2;
    if(num<=mid)update(ls[o],l,mid,k,num);
    else update(rs[o],mid+1,r,k,num);
}
ll query(int o,int l,int r,ll k){
    if(l==r)return 1LL*k*l%mod;
    int mid=(l+r)/2;
    ll res=0;
    if(k>sum[ls[o]])res=(val[ls[o]]+query(rs[o],mid+1,r,k-sum[ls[o]]));
    else res=query(ls[o],l,mid,k);
    return res%mod;
}


int main()
{
    int q,rt=0;
    cin>>q;
    while(q--){
        int op;ll l,r;
        cin>>op>>l>>r;
        if(op==1)update(rt,0,1e9,l,r);
        else{
            cout<<(query(rt,0,1e9,r)-query(rt,0,1e9,l-1)+mod)%mod<<endl;
        }
    }
    return 0;
}

简单数学题 (数学题)

思路

\(F(n) = \sum_{i=1}^n (i \times \sum_{j=i}^n C_j^i)\)

->$F(n)=\sum_{i=1}^{n}\sum_{j=i}^{n} i \times C_{j}^{i} $

其中$ \sum C_{j}^{i}$ 是杨辉三角的一条斜线

然后把i乘入这个斜线中,发现杨辉三角变成一个新的少了一维的杨辉三角

发现新的杨辉三角是之前的杨辉三角每一层的元素乘上层号

然后就是变成求\(\sum_{i=1}^{n} i\times 2^{i-1}\)

\(1\times 2+2 \times2^1 +3 \times 2^2+\dots n \times2^{n-1}\)

然后拆项为
\[ 2^1+2^2+2^3+2^4 \dots2^{n-1}\\+2^2+2^3+2^4+\dots2^{n-1} \\ +2^3+2^4+\dots2^{n-1}\\+2^4+\dots2^{n-1}\\ \dots \]
根据等比数列\(s_n=\frac{a_1(1-a_n)}{1-q}=\frac{a_nq-a_1}{q-1}\)

整理

第一行变成\(2^n-2^0\) 第二行变成\(2^n-2^1\) 第n行变成\(2^n-2^{n-1}\)

再整理变成\(n\times2^n-(2^n-1)=(n-1)\times2^n+1\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll mod=1e9+7;
const int maxn=5e5+50;
const int inf=1e8;
ll ksm(ll a,ll b){
    ll ans=1;
    while(b){
        if(b&1)ans=(ans*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return ans;
}
int main()
{
    ll n;
    while(~scanf("%lld",&n)){
        ll ans=ksm(2,n);
        n%=mod;
        ans=(ans*(n-1))%mod;
        ans+=1;ans%=mod;
        printf("%lld\n",ans);
    }
    return 0;
}

zyb的面试 (原题)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll mod=1e9+7;
const int maxn=1e3+50;
const ll inf=1e17;
int cal(int n,int k){
    int cur=1;
    k=k-1;
    while(k>0){
        int step=0,first=cur,last=cur+1;
        while(first<=n){
            step+=min(n+1,last)-first;
            first*=10;
            last*=10;
        }
        if(step<=k){
            cur++;
            k-=step;
        }
        else{
            cur*=10;
            k-=1;
        }
    }
    return cur;
}
int main()
{
    int t;
    cin>>t;
    while(t--){
        int n,k;
        cin>>n>>k;
        cout<<cal(n,k)<<endl;
    }
    return 0;
}

Count (矩阵快速幂)

思路

考虑矩阵快速幂 考虑要从前一项得到后一项的\(n^3\)

根据公式\((n+1)^3=n^3+3*n^2+3*n+1\)

推出\(f(n)=f(n-1)+2*f(n-2)+n^3+3*n^2+3*n+1\)

所以构造一个矩阵就行了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pp pair<int,int>
const ll mod=123456789;
const int maxn=1e6+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
#define bug cout<<"here"<<endl;
typedef vector<ll>vec;
typedef vector<vec>mat;

mat mul(mat& A,mat &B){
    mat C(A.size(),vec(B[0].size()));
    for(int i=0;i<A.size();i++)
        for(int k=0;k<B.size();k++)
        if(A[i][k])
            for(int j=0;j<B[0].size();j++)
            C[i][j]=(C[i][j]+A[i][k]*B[k][j]%mod+mod)%mod;
    return C;
}
mat Pow(mat A,ll n){
    mat B(A.size(),vec(A.size()));
    for(int i=0;i<A.size();i++)B[i][i]=1;
    for(;n;n>>=1,A=mul(A,A))
        if(n&1)B=mul(B,A);
    return B;
}

int main(){
    int q;
    scanf("%d",&q);
    while(q--){
        ll n;
        scanf("%lld",&n);
        if(n==1){
            printf("1\n");continue;
        }
        else if(n==2){
            printf("2\n");continue;
        }
        mat a(6,vec(6));
        a[0][0]=1;a[0][1]=2;a[0][2]=1;a[0][3]=3;a[0][4]=3;a[0][5]=1;
        a[1][0]=1;a[1][1]=0;a[1][2]=0;a[1][3]=0;a[1][4]=0;a[1][5]=0;
        a[2][0]=0;a[2][1]=0;a[2][2]=1;a[2][3]=3;a[2][4]=3;a[2][5]=1;
        a[3][0]=0;a[3][1]=0;a[3][2]=0;a[3][3]=1;a[3][4]=2;a[3][5]=1;
        a[4][0]=0;a[4][1]=0;a[4][2]=0;a[4][3]=0;a[4][4]=1;a[4][5]=1;
        a[5][0]=0;a[5][1]=0;a[5][2]=0;a[5][3]=0;a[5][4]=0;a[5][5]=1;
        mat f(6,vec(1));
        f[0][0]=2;
        f[1][0]=1;
        f[2][0]=8;
        f[3][0]=4;
        f[4][0]=2;
        f[5][0]=1;
        a=Pow(a,n-2);
        f=mul(a,f);
        printf("%lld\n",f[0][0]);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/luowentao/p/10545142.html