zoukankan      html  css  js  c++  java
  • HDU4669_Mutiples on a circle

    题目的意思是给你一些数字a[i](首位相连),现在要你选出一些连续的数字连续的每一位单独地作为一个数位。现在问你有多少种选择的方式使得选出的数字为k的一个倍数。

    其实题目是很简单的。由于k不大(200),总共的数字个数为50000,所以我们对于当前走到的每一个数字最多的状态数目也只有50000*200个。

    同时由于是循环的,我们可以使长度增倍,这样就可以保证序列是循环的了。

    不过注意,增倍后空间是开不下的,所以需要使用循环的滚动数组。

    同时注意递推的细节,还有有的a[i]不止一位数,不能直接取模。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define maxn 50050
    typedef long long ll;
    using namespace std;
    
    int a[2*maxn],f[2*maxn],n,m,k,tep,cur,w[2*maxn];
    int s[maxn][205];
    ll ans;
    
    void init_(int x)
    {
        for (int i=0; i<k; i++) s[x][i]=0;
    }
    
    int count(int x)
    {
        if (x<10) return 1;
        if (x<100) return 2;
        if (x<1000) return 3;
        return 4;
    }
    
    int get(int x)
    {
        if (x==1) return 10;
        if (x==2) return 100%k;
        if (x==3) return 1000%k;
        return 10000%k;
    }
    
    int power(int x,int y)
    {
        int tot=1;
        while (y)
        {
            if (y&1) tot=(tot*x)%k;
            y>>=1;
            x=(x*x)%k;
        }
        return tot;
    }
    
    int main()
    {
        while (scanf("%d%d",&n,&k)!=EOF)
        {
            ans=0;
            w[0]=0,f[0]=0;
            for (int i=1; i<=n; i++)
            {
                scanf("%d",&a[i]);
                a[i+n]=a[i];
                w[i]=count(a[i]);
                w[i+n]=count(a[i+n]);
            }
            for (int i=1; i<=2*n; i++) f[i]=(f[i-1]*get(w[i])+a[i])%k;
            for (int i=1; i<=2*n; i++) w[i]+=w[i-1];
            for (int i=1; i<=n; i++)
            {
                init_(i);
                s[i][a[i]%k]++;
                for (int j=0; j<k; j++) s[i][(get(w[i]-w[i-1])*j+a[i])%k]+=s[i-1][j];
            }
            for (int i=n+1; i<=2*n; i++)
            {
                int qq=i-n-1;
                if (qq==0) qq=n;
                init_(i-n);
                s[i-n][a[i]%k]++;
                for (int j=0; j<k; j++) s[i-n][(get(w[i]-w[i-1])*j+a[i])%k]+=s[qq][j];
                cur=(f[i-n-1]*power(10,w[i]-w[i-n-1]))%k;
                cur=((f[i]-cur)%k+k)%k; 
                s[i-n][cur]--; 
                ans+=s[i-n][0];
            }
            printf("%I64d
    ",ans);
        }
        return 0;
    }
    如有转载,请注明出处(http://www.cnblogs.com/lochan)
  • 相关阅读:
    线程安全
    C++和java中构造函数与析构函数的调用顺序
    mysql数据库的备份与恢复
    Spring Web Flow 2.0 入门详解
    JBOSS 5.0与tomcat 6.0端口设置
    修改mysql root密码
    Subversion Native Library Not Available
    解决Eclipse导入svn项目自动关闭
    将eclipse中项目的Text File Encoding设置成为GBK
    java下实现调用oracle的存储过程和函数
  • 原文地址:https://www.cnblogs.com/lochan/p/3446851.html
Copyright © 2011-2022 走看看