zoukankan      html  css  js  c++  java
  • hihocoder1033交错和

    题目链接

    坑:

    1.ll x,y;

    z=x*y;可能会溢出,于是我写成x%mod*y%mod

    仍旧错误,要写成x%mod*(y%mod).

    2.f(9019)=1.

    要注意如果为0,下一位的符号根据0的个数而变化

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<algorithm>
     4 #include<queue>
     5 #include<math.h>
     6 #include<string.h>
     7 #include<string>
     8 #include<stdlib.h>
     9 using namespace std;
    10 typedef long long ll;
    11 typedef unsigned long long ull;
    12 #define re(i,n) for(int i=0;i<n;i++)      
    13 const int mod = 1e9 + 7;
    14 /*
    15 Node cnt表示个数,sum表示和
    16 */
    17 struct Node{
    18     ll cnt, sum;
    19     Node() :cnt(0), sum(0){}
    20     Node(ll c, ll s) :cnt(c), sum(s){}
    21 }dp[19][2][2][600];//(bits,+-,+-can change,sum)
    22 /*
    23 19 最多19位
    24 2  +还是-
    25 2  是否是第一个数字
    26 600 f(n)的结果,因为19位*9=171,输入的k是-100到100,所以范围大概是-300到+300,所以用600
    27 */
    28 ll ten[19];
    29 //ten[i]表示10^i
    30 void init(){
    31     ten[0] = 1;
    32     for (int i = 1; i < 19; i++){
    33         ten[i] = 10 * ten[i - 1];
    34     } 
    35 }
    36 /*d是一个大管家,管理者dp这个数组,如果计算过,那就不再计算了
    37 对参数做一些处理,像适配器一样
    38 n表示[0,10^n-1]范围内,第一个符号为flag,符号是否会改变change,f(n)=k
    39 */
    40 Node d(int n, int flag, int change, int k){
    41     int ff = (flag == 1 ? 1 : 0);
    42     int kk = k + 300;
    43     Node f(ll,int, int, int);
    44     if (dp[n][ff][change][kk].cnt == -1){
    45         dp[n][ff][change][kk] = f(ten[n] - 1, flag, change, k);
    46     }
    47     return dp[n][ff][change][kk];
    48 }
    49 /*
    50 主要逻辑都在这个函数里面,n表示[0,n]范围内的值
    51 */
    52 Node f(ll n, int flag, int change, int k){ 
    53     if (n < 0)return Node(0, 0);
    54     if (n < 10){
    55         if (flag*k >= 0 && flag*k <= n)return Node(1, flag*k);
    56         else return Node(0, 0);
    57     }
    58     ll mi = 0, h = 0; 
    59     for (ll tmp = n; tmp; tmp /= 10)h = tmp % 10, mi++;
    60     mi--;
    61     ll va = h*ten[mi];//处理清楚最高位
    62     Node t = d(mi, change ? 1 : -flag, change, k); //第一位为0时,有多少种情况
    63     Node ans = t;
    64     for (int i = 1; i < h; i++){
    65         t = d(mi, -flag, 0, k - flag*i); 
    66         ans.cnt += t.cnt;
    67         ans.sum = (ans.sum + ten[mi]%mod*i*( t.cnt%mod) + t.sum) % mod;
    68     }
    69     //第一位为h时的情况
    70     int ff = ((mi&1)?flag:-flag);
    71     for (ll tmp=n-va; tmp; tmp/=10){
    72         ff *= -1;  
    73     }
    74     t = f(n - va, ff, 0, k - flag*h); 
    75     ans.cnt += t.cnt;
    76     ans.sum = (ans.sum + va%mod*(t.cnt%mod) + t.sum) % mod;
    77     return ans;
    78 } 
    79 int main(){
    80     //freopen("in.txt", "r", stdin);
    81     init();
    82     memset(dp, -1, sizeof(dp));
    83     ll l, r, k;
    84     cin >> l >> r >> k;
    85     Node m = f(l - 1, 1,1, k), n = f( r, 1,1, k);
    86     ll ans = (n.sum - m.sum) % mod;
    87     if (ans < 0)ans += mod; 
    88     cout << ans << endl; 
    89     return 0;
    90 }

    别人的代码还精简,算法更好.

     1 struct node  
     2 {  
     3     ll cnt,sum; //分别表示该状态的出现的次数,以及数字和  
     4     node(ll _cnt,ll _sum):cnt(_cnt),sum(_sum){}  
     5     node(){}  
     6 }dp[20][20][300]; //dp[i][j][k],表示当前在的i位,第一位有效位为j,交错和为k-100的状态  
     7 ll num[20];  
     8 ll ten[20];  
     9 ll l,r;  
    10 int k;  
    11 node dfs(int cur,int first,int sum,bool limit)  
    12 {  
    13     if(cur <= 0)  
    14         return node(sum==k,0);  
    15     if(!limit && dp[cur][first][sum+100].cnt != -1) return dp[cur][first][sum+100];  
    16     int up = limit ? num[cur] : 9;  
    17     node ret(0,0),tv;  
    18     rep(i,up+1)  
    19     {  
    20         int g;  
    21         if(!first){ g = (i == 0 ? 0 : cur); }  
    22         else g = first;  
    23         if(g)  
    24             tv = dfs(cur-1,g,sum+((g-cur)%2==0?1:-1)*i,limit && i == up);  
    25         else  
    26             tv = dfs(cur-1,0,0,limit && i==up);  
    27         ll t = i*ten[cur-1]%mod;  
    28         ret.cnt = (ret.cnt + tv.cnt) % mod; //次数相加  
    29         ret.sum = (ret.sum + tv.sum + t*tv.cnt)%mod; //和相加  
    30     }  
    31     if(!limit) dp[cur][first][sum+100] = ret;  
    32     return ret;  
    33 }  
    34 ll solve(ll n)  
    35 {  
    36     if(n <= 0) return 0;  
    37     int len = 0;  
    38     while(n){  
    39         num[++len] = n % 10;  
    40         n /= 10;  
    41     }  
    42     return dfs(len,0,0,1).sum;  
    43 }  
    44 void init()  
    45 {  
    46     memset(dp,-1,sizeof(dp));  
    47     ten[0] = 1;  
    48     for(int i=1;i<20;i++) ten[i] = (ten[i-1] * 10) % mod;  
    49 }  
    50 int main()  
    51 {  
    52 #ifndef ONLINE_JUDGE  
    53     freopen("in.txt","r",stdin);  
    54     // freopen("out.txt","w",stdout);  
    55 #endif    
    56     init();  
    57     while(~scanf("%lld%lld%d",&l,&r,&k))  
    58     {  
    59         cout<<(solve(r)-solve(l-1)+mod)%mod<<'
    ';  
    60     }  
    61     return 0;  
    62 }  
  • 相关阅读:
    JQuery UI
    JQuery 插件
    JQuery Ajax
    varchar和Nvarchar区别
    git冲突解决
    jquery ajax 提交信息后等待返回的提示信息
    Oracle错误 ORA-12560如何解决
    putty ssh连接老断
    myeclipse操作记录
    HTML与HTML5笔记
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/4902595.html
Copyright © 2011-2022 走看看