Cf 104 div.2

A题

if all digits are lucky and sum of the digits of the first half equals to the sum of the digits of the second half, then answer is YES, in other case - NO. All this can be checked by single loop through all the digits


B题

 in worst case, the answer will be equal to  177777. It can't be greater. So, only thing you need is to write some function  F(x)which will return mask of the  x. After that you need to write such kind of code: 
x =  a + 1;

while ( F(x) is not equal to  b)

increase  x;

and  x will contain the answer.


C题

You need to find two numbers: c47 (number of such positions i, that ai = 4 and bi = 7) and c74 (number of such positions that ai = 7 and bi = 4). After that the result will be max(c47, c74) (because you need to obtain min(c47, c74) swaps, the rest max(c47, c74) - min(c47, c74)are editings of digits).


D题

这题,比赛的时候花了一个小时,结果还是wa。。。

我花了20分钟的时间推出了个结论,如果 | a3-a4 | > 1,则输出 -1 。。。这个很重要。

1、a3==a4

细分:

  1、 a1==a3 && a2>a4                  2、a1>a3 && a2==a4                 3、a1>a3&& a2>a4


2、a3== a4+1

必须: a1>=a3 && a2>=a3

4...4747474777...7


3、a4== a3+1

必须: a1>=a4 && a2>=a4

比较特殊的吧:

74

74444...4

77774444

7444...44747477...774


E题

首先,相同的lucky num数放一起,

题目转换成,n个数里面挑k个数来乘,把所有的结果累加,注意取模。

开始是想dp[][],可以搞定,可是n,k如此大,吗,,,,,,,,,看题解,它说lucky num在[1, 10^9]里就1022个,顿时傻眼,于是就明朗了。

设cnt为非lucky_num的个数;

C( cnt, t ) * dp[ n ][ k-t ] % mod;   注意,我这里一直错误。。。t有界限的, 

for ( t= max( 0, k-n ); t<=k && t<=cnt ; ++t )

关于C(a,b)%mod,我是考虑到a,b<=10^5, 可以事先打表搞定 x! % mod, 注意下面一个大牛的代码,把逆元也事先全部算出来了,这个在ACM的比赛里确实是值得借鉴。


我的代码:

/*Jan 23, 2012 12:40:06 PM	yimao	 E - Lucky Subsequence	 GNU C++	Accepted	 280 ms	 10900 KB*/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <map>
#include <string>
using namespace std;
#define MM(a,b) memset(a,b,sizeof(a));
typedef unsigned long long u64;
typedef long long lld;
#define maxn 100050
#define mod 1000000007

map<string,int>M;

bool judge(string x){
    for(int i=0;i<x.size();++i)
        if( x[i]!='4'&&x[i]!='7' ) return 0;
    return 1;
}

// dp[i][j]: the number of within [1,i],choose j lucky number;
int a[1050];
lld dp[1050][1050]; // the number of lucky number if 1022 in [1,10^9];
void DP(int n,int k){
    MM( dp, 0 );
    for(int i=0;i<=n;++i) dp[i][0]= 1; /// i=0;
    for(int i=1;i<=n;++i){
        for(int j=1;j<=k&&j<=i;++j){
            dp[i][j]= (dp[i-1][j] + (a[i]*dp[i-1][j-1])%mod) %mod;
        }
    }
}

lld x[maxn];
void Init(){
    x[0]=1;
    for(lld i=1;i<=100000;++i)
        x[i]= (x[i-1]*i)%mod;
}

lld Pow_mod(lld x,lld k){
    lld r=1,t=x%mod;
    while(k){
        if(k&1) r= r*t%mod;
        t= t*t%mod;
        k>>=1;
    }
    return r%mod;
}
// calu C(a,b)%p, p is a prime(1000000007),a,b<=10^5;
lld Comb(int a,int b){
    lld t= (x[b]*x[a-b])%mod;
    lld w= Pow_mod( t, mod-2 );
    return ( x[a]* w )%mod;
}

int main()
{
    //freopen("E.txt","r",stdin);
    int i,n,k;
    Init();
    while(cin>>n>>k){
        if( !M.empty() ) M.clear();
        string ch;
        int cnt=0; // num of digit 1;
        for(i=0;i<n;++i){
            cin>> ch;
            if( judge(ch)==0 ) cnt++;
            else{
                if( M.find(ch)==M.end() )
                    M[ch]=1;
                else M[ch]++;
            }
        }
        //if( k>n ) { puts("0"); continue; } the problem says k<=n;

        n= 0;
        for(map<string,int>::iterator it= M.begin();it!=M.end();++it){
            a[++n]= it->second;
        }
        //printf("n=%d\n",n);

        DP(n,k);
        lld sum=0;
        //for(i=0;i<=cnt&&i<=k;++i){
        for(i=max(0,k-n);i<=cnt&&i<=k;++i){
            sum+= ( Comb(cnt,i) * dp[n][k-i] )%mod;
            if( sum>=mod ) sum-= mod;
        }
        cout<< sum <<endl;
    }
}

一个大牛的代码,非常nb:

#include<stdio.h>
#include<string>
#include<math.h>
#include<stdlib.h>
#include<set>
#include<bitset>
#include<map>
#include<vector>
#include<string.h>
#include<algorithm>
#include<iostream>
#define pb push_back
#define MOD 1000000007
using namespace std;
vector<int>lucky;
void dfs(int x){
    int y;
    if(x>=100000000)return;
    y=x*10+4;
    lucky.pb(y);
    dfs(y);
    y=x*10+7;
    lucky.pb(y);
    dfs(y);
}
int a[1024];
long long dp[1024],inv[100010],fac[100010];
long long mypow(long long x,long long y){
    long long an=1;
    while(y){
        if(y&1){
            an*=x;
            an%=MOD;
        }
        y>>=1;
        x*=x;
        x%=MOD;
    }
    return an;
}
int main(){
    int i,j,k,n,non=0,m;
    fac[0]=inv[0]=1;
    for(i=1;i<=100000;i++){
        fac[i]=fac[i-1]*i%MOD;
    }
    inv[100000]=mypow(fac[100000],MOD-2);
    for(i=99999;i>0;i--)inv[i]=inv[i+1]*(i+1)%MOD;
    dfs(0);
    sort(lucky.begin(),lucky.end());
    scanf("%d%d",&n,&k);
    m=min((int)lucky.size(),k);
    for(i=0;i<n;i++){
        int x;
        scanf("%d",&x);
        int tmp=lower_bound(lucky.begin(),lucky.end(),x)-lucky.begin();
        if(tmp>=lucky.size())non++;
        else if(lucky[tmp]==x)a[tmp]++;
        else non++;
    }
    dp[0]=1;
    for(i=0;i<lucky.size();i++){
        for(j=m;j>0;j--){
            dp[j]=(dp[j-1]*a[i]+dp[j])%MOD;
        }
    }
    long long an=0;
    for(i=0;i<=m;i++){
        if(k-i>non)continue;
        an+=dp[i]*fac[non]%MOD*inv[k-i]%MOD*inv[non-(k-i)]%MOD;
    }
    an%=MOD;
    if(an<0)an+=MOD;
    cout<<an<<endl;
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值