一拨水题(变成各个位平分和,1~n字典序排序,矩阵快速幂,线段树)

超级无敌简单题

题意: 鸽子数字由以下过程定义:从任何正整数开始,将数字替换为其各个数位的平方和,并重复该过程,直到该数字等于1。如果不能,则这个数字不是鸽子数。
例如7是鸽子数,因为7->49->97->130->10->1。(77=49,44+99=97,99+7*7=130…如此类推)

解析:

打了一遍表,发现在一定次数后要么出现循环,要么变成1。而且一个数变成小于1000后就不能再大于1000了。所以,打出1000内的数。一直做暴力直到小于1000,判断是否为答案。

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(register int i=a;i<=b;i++)
#define repp(i,a,b) for(register int i=a;i>=b;i--)
#define mmm(p) memset(p,0,sizeof p)
#define pill pair<int,int>
#define debug(i) printf("#%d\n",i)
typedef long long LL;
int read(){ int ans=0; char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}


int ar[167]={1,7,10,13,19,23,28,31,32,44,49,68,70,79,82,86,91,94,97,
100,103,109,129,130,133,139,167,176,188,190,192,193,203,208,219,226,
230,236,239,262,263,280,291,293,301,302,310,313,319,320,326,329,331,
338,356,362,365,367,368,376,379,383,386,391,392,397,404,409,440,446,
464,469,478,487,490,496,536,556,563,565,566,608,617,622,623,632,635,
637,638,644,649,653,655,656,665,671,673,680,683,694,700,709,716,736,
739,748,761,763,784,790,793,802,806,818,820,833,836,847,860,863,874,
881,888,899,901,904,907,910,912,913,921,923,931,932,937,940,946,964,
970,973,989,998,1000,1003,1009,1029,1030,1033,1039,1067,1076,1088,1090,
1092,1093,1112,1114,1115,1121,1122,1125,1128,1141,1148,1151,1152,1158};

int ans[150009];
bool vis[2000];
bool check(int i){
    while(1){
        if(i<=1158){
            if(vis[i])return 1;
            return 0;
        }
        int sum=0;
        while(i>0){
            sum+=i%10*(i%10);
            i/=10;
        }
        i=sum;
        if(i==1)return 1;
    }
    return 0;
}
void init(){
    int ct=0;
    for(int i=0;i<167;i++)vis[ar[i]]=1;
    for(int i=1;;i++){
        if(check(i))ct++,ans[ct]=i;
        if(ct==150000)break;
    }
}
int main(){
    init();
    int q=read();
    while(q--){
        int id=read();
        printf("%d\n",ans[id]);
    }
}

zyb的面试

题意: 1到n的排列,按字典序排,n=15时排列顺序为1, 10, 11, 12, 13, 14, 15, 2, 3, 4, 5, 6, 7, 8, 9。问n的排序中第k个数。

解析:

求出pre带头的数有几个,一步一步dfs下去直到答案即可。注意从x跳到x*10带头时,需要need-1,因为x也算一个数。

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(register int i=a;i<=b;i++)
#define repp(i,a,b) for(register int i=a;i>=b;i--)
#define mmm(p) memset(p,0,sizeof p)
#define pill pair<int,int>
#define debug(i) printf("#%d\n",i)
#define D long long
typedef long long LL;
int read(){ int ans=0; char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
const int N=7;
const LL mod=123456789;
int n,k;
int find(int pre){
    int sum=0;
    for(int i=1;;i*=10){
        if(pre*i<=n){
            int en=pre*i+i-1;
            if(en<=n){
                sum+=i;
            }
            else{
                sum+=n-pre*i+1;
                break;
            }
        }
        else{
            break;
        }
    }
    return sum;
}

int dfs(int p,int need){
    if(need==1)return p;
    int have=find(p);
    if(have<need){
        need-=have;
        return dfs(p+1,need);
    }
    else{
        p*=10;
        return dfs(p,need-1);
    }
}

int main(){
    int t=read();
    while(t--){
        n=read(),k=read();
        find(100);
        int ans=dfs(1,k);
        printf("%d\n",ans);
    }
}

Count

题意: 第一头奶牛为1号,第二头奶牛为2号,第三头奶牛之后,假如当前奶牛是第n头,那么他的编号就是2倍的第n-2头奶牛的编号加上第n-1头奶牛的编号再加上自己当前的n的三次方为自己的编号.求第n只编号。

解析:

矩阵快速幂
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(register int i=a;i<=b;i++)
#define repp(i,a,b) for(register int i=a;i>=b;i--)
#define mmm(p) memset(p,0,sizeof p)
#define pill pair<int,int>
#define debug(i) printf("#%d\n",i)
#define D long long
typedef long long LL;
int read(){ int ans=0; char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
const int N=7;
const LL mod=123456789;
struct matrix{
    int size;
    D mat[N][N];
    matrix(int s){
        size=s;for(int i=1;i<=s;i++)for(int j=1;j<=s;j++)mat[i][j]=0;
    }
    matrix operator * (const matrix & x)const{
        matrix ans(x.size);
        for(int i=1;i<=x.size;i++){
            for(int j=1;j<=x.size;j++){
                for(int k=1;k<=x.size;k++){
                    ans.mat[i][j]=((ans.mat[i][j]+mat[i][k]*x.mat[k][j])%mod+mod)%mod;
                }
            }
        }return ans;
    }
} ;
matrix swift(matrix a,D t){
    matrix ans(a.size);
    for(int i=1;i<=a.size;i++)ans.mat[i][i]=1;
    while(t){
        if(t&1ll)ans=ans*a;
        a=a*a;t>>=1;
    }return ans;
}

matrix b(6);
matrix a(6);
void init(){
    b.mat[1][1]=1;
    b.mat[1][2]=1;
    b.mat[2][1]=2;
    b.mat[3][1]=1;
    b.mat[3][3]=2;
    b.mat[3][4]=1;
    b.mat[4][3]=-1;
    b.mat[5][3]=6;
    b.mat[5][5]=1;
    b.mat[6][5]=1;
    b.mat[6][6]=1;
    a.mat[1][1]=2;
    a.mat[1][2]=1;
    a.mat[1][3]=27;
    a.mat[1][4]=8;
    a.mat[1][5]=3;
    a.mat[1][6]=1;
}

int main(){
    int t=read();
    while(t--){
        LL n;
        scanf("%lld",&n);
        init();
        n-=2;
        a=a*swift(b,n);
        printf("%lld\n",a.mat[1][1]);
    }
}

免费送气球

题意: 已知一开始有一个空序列,接下来有Q次操作,每次操作给出type、first和second三个值。当type为1时,意味着该操作属于第一种操作:往序列尾部添加first个second数。当type为2时,意味着该操作属于第二种操作:查询序列中第first小至第second小的数值之和(一共有(second - first + 1)个数被累加),并将结果对1000000007取模后输出。

解析:

对数的大小进行离散化再线段树,每个节点记录点的数量,点权和。点权和需要取模,但是点的数量不需要,因为long long存的下(如果数量需要取模难度可能不是一遍的大,因为很多时候需要进行数量的比较)。
注意如果query进行到了l==r,且点数大于需要的,得进行权值的计算。

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(register int i=a;i<=b;i++)
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs ((rt<<1)|1)
#define LL long long
const LL mod = 1000000007;
const int maxn=100000+5;

struct node{
    int f;LL x,y;
}e[maxn];
LL tmp[maxn];

LL siz[maxn<<2],sum[maxn<<2];
void add(int rt,int l,int r,LL x,LL y){
    siz[rt]+=x;
    sum[rt]=(sum[rt]+x*tmp[y])%mod;
    if(l==r)return;
    if(y<=mid)add(ls,l,mid,x,y);
    else add(rs,mid+1,r,x,y);
}

LL query(int rt,int l,int r,LL num){
    if(num==0)return 0;
    if(l==r){
        if(num>=siz[rt])return sum[rt];
        else return num*tmp[l]%mod;
    }
    if(num>=siz[rt]){
        return sum[rt];
    }
    if(num>=siz[ls]){
        return (sum[ls]+query(rs,mid+1,r,num-siz[ls])%mod);
    }
    return query(ls,l,mid,num);
}

int main(){
    int q;scanf("%d",&q);
    int qq=0;
    rep(i,1,q){
        scanf("%d%lld%lld",&e[i].f,&e[i].x,&e[i].y);
        if(e[i].f==1)tmp[++qq]=e[i].y;
    }
    sort(tmp+1,tmp+1+qq);
    int num=unique(tmp+1,tmp+1+qq)-tmp-1;
    rep(i,1,q){
        if(e[i].f==1)
            e[i].y=lower_bound(tmp+1,tmp+1+num,e[i].y)-tmp;
    }
    rep(i,1,q){
        if(e[i].f==1){
            add(1,1,num,e[i].x,e[i].y);
        }
        else{
            printf("%lld\n",(query(1,1,num,e[i].y)-query(1,1,num,e[i].x-1)+2*mod)%mod);
        }
    }

}

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/88615425