2019.8.19小结

T1 阶乘 100/100

题意

T组数据,给出N,求出N!最右边非零的数。

对于30%的数据,N <= 30,T<=10。

对于全部的数据,N <= 10^2009,T<=30。

一道数学题

解析

N!/(10x)最后一位数字即是结果。10x进行拆分,变成5x*2x。怎么除以5^x呢,好办,乘的时候含有5的倍数的一项全部不乘进去,再递归此过程。即

1 2 3 4 (15) 6 7 8 9 (25)

11 12 13 14 (35)16 17 18 19 (45)

21 22 23 24 (55) 26 27 28 29 (65) ...

再递归处理

1 2 3 4 (1*5) 6

而且可以发现,不算5倍数一项进去,每十个一组,最末尾结果是一样的:6,且6*6还是6!

接下来的问题,怎么除2^x呢?

分析发现:

2^0 = 1

2^1 = 2

2^2 = 4

2^3 = 8

2^4 =16=(6)

且2,4,6,8乘以6最末尾还是原来的数。所以,可以分析看x%4是多少,若为1,说明原来的结果相当于多乘了一个2(其他的那些2刚好是4的倍数,不影响结果),所以,我们本来是要除以2的,但是很显然对结果再补乘3个2(2^3)即可消除影响,得到正确答案。其他情况同理。至此,思路理顺。

代码

#include<bits/stdc++.h>
using namespace std;
int T,n,ans,mod,rest,x;
bool flag;
const int v[10]={1,1,2,6,4,4,4,8,4,6};
char s[3000];
int a[3000];
const int k[4]={6,8,4,2};
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%s",s);
        memset(a,0,sizeof(a));
        n=strlen(s);
        for(int i=1;i<=n;++i){
            a[i]=s[n-i]-'0';
        }
        ans=1;
        mod=0;
        flag=0;
        while(1){
            rest=0;
            ans=(ans*v[a[1]])%10; 
            if(n>1) ans=(ans*6)%10;
            for(int i=n;i>=1;i--){
                x=rest*10+a[i];
                rest=x%5;a[i]=x/5;
            }
            while((n>0)&&(a[n]==0)) n--;
            if(n==0) break;
            flag=true;
            mod=(mod+a[2]*10+a[1])%4; 
        }
        if(flag) ans=(ans*k[mod])%10;
        printf("%d\n",ans);
    }
    return 0;
}

T2 拐弯 30/90

题意

给出n* n 的图,A为起点,B为终点,*为障碍,.可以行走,问最少需要拐90度的弯多少次,无法到达输出-1。

解析

考场爆搜以为大部分过不去,结果有90分

思路:构造N * M * 4个点,即将原图的每个点分裂成4个点。其中点(i,j,k)表示在(i,j)时人的方向是k,然后对于两个点(i,j,k)和(i,j,kk),如果k和kk是两个旋转90度能转换的方向,就连一条边权为1的边,而对于(i,j,k)和(i+dx[ k],j+dy[k],k)连一条边权为0的边,表示从(i,j)在方向为k的情况下能向k方向走一步到达(i+dx[k],j+dy[k],k)。因为起始和终止的方向不确定,故再添加一个源点和一个汇点,源点向起始位置四个方向连边权为0的边,汇点向终止位置四个方向连边权为0的边,然后求源点到汇点的最短路即可。

爆搜代码

#include<bits/stdc++.h>
using namespace std;
int n,sx,sy,ex,ey,a[110][110];
char k;
bool book[110][110];
int ans=1<<30;
bool cheak(int x,int y){
    if(x<1||y>n||y<1||x>n||a[x][y]||book[x][y]) return false;
    else return true;
}
void dfs(int x,int y,int dir,int step){
    if(x==ex&&y==ey){
        ans=min(step,ans);
        return;
    }
    if(step>ans) return;
    if(dir){
        if(cheak(x+1,y)){
            book[x+1][y]=1;
            dfs(x+1,y,dir,step);
            book[x+1][y]=0;
        }
        if(cheak(x-1,y)){
            book[x-1][y]=1;
            dfs(x-1,y,dir,step);
            book[x-1][y]=0;
        }
        if(cheak(x,y+1)){
            book[x][y+1]=1;
            dfs(x,y+1,0,step+1);
            book[x][y+1]=0;
        }
        if(cheak(x,y-1)){
            book[x][y-1]=1;
            dfs(x,y-1,0,step+1);
            book[x][y-1]=0;
        }
    }
    else{
        if(cheak(x+1,y)){
            book[x+1][y]=1;
            dfs(x+1,y,1,step+1);
            book[x+1][y]=0;
        }
        if(cheak(x-1,y)){
            book[x-1][y]=1;
            dfs(x-1,y,1,step+1);
            book[x-1][y]=0;
        }
        if(cheak(x,y+1)){
            book[x][y+1]=1;
            dfs(x,y+1,dir,step);
            book[x][y+1]=0;
        }
        if(cheak(x,y-1)){
            book[x][y-1]=1;
            dfs(x,y-1,0,step);
            book[x][y-1]=0;
        }
    }
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        for(int j=1;j<=n;++j){
            scanf("%c",&k);
            if(k=='A'){
                sx=i;
                sy=j;
            }
            else if(k=='B'){
                ex=i;
                ey=j;
            }
            else if(k=='x'){
                a[i][j]=1;
            }
            else if(k=='.'){
                a[i][j]=0;
            }
            else j--;
        }
    }
    dfs(sx,sy,0,0);
    dfs(sx,sy,1,0);
    if(ans==1<<30) printf("-1");
    else printf("%d",ans);
    return 0;
}

T3 天天爱跑步 20/20

题意

自行百度 noip题

考场按特殊点打的,20分。

代码

T4 填数游戏 100/95

题意

自行百度 noip题

解析:规律题,证明等以后来补

考场快速幂取模有点问题,溢出了,所以丢了5分

代码

#include<bits/stdc++.h>
using namespace std;
long long n,m;
long long ans;
long long f[10];
const long long mod=1e9+7;
long long power(int x,int y){
    long long tmp=1;
    while(y){
        if(y&1) tmp=(x*tmp)%mod;
        x=(x%mod*x%mod)%mod;
        y>>=1;
    }
    return tmp;
}
int main(){
    scanf("%lld %lld",&n,&m);
    f[1]=2;
    for(int i=2;i<=9;++i){
        f[i]=f[i-1]*2;
    }
    if(n>m) swap(n,m);
    if(n==1){
        ans=power(2,m);
        printf("%lld",ans%mod);
        return 0; 
    } 
    else if(n==2) ans=12;
    else if(n==3) ans=112;
    else if(n==4) ans=912;      
    else{
        ans=912;
        for(int i=5;i<=n;++i){
            ans=(ans*8-5*f[i])%mod;
        }
    }       
    if(m==n+1&&n>3) ans=ans*3-3*f[n];
    else if(m==n+1) ans=ans*3;
    if(m>n+1){
        if(n>3) ans=ans*3-3*f[n];
        else ans=ans*3;
        for(int i=n+2;i<=m;++i){
            ans=ans*3%mod;
        }
    }
    printf("%lld",ans%mod);
    return 0;
}
posted @ 2019-08-26 21:10  End_donkey  阅读(148)  评论(0编辑  收藏  举报