A-小睿睿的等式

theme:给定n、k(n%k==0,0<=n<=50000000;A,B>=0)表示开始时有根火柴,问满足摆成A+B=n所使用的火柴数为n/k的等式有几种(B+A=n与A+B=n看作一种),+、=各用两根

数字摆法为:

牛客oi周赛7

solution:枚举。基本思路是用n减去摆n和+、=所用的火柴数得到摆A、B所需个数,然后从0到n/2遍历等式得A,B,找到所需火柴数符合的。对于每个数字用%与/得到各个数为求。

注意:这题n可达5*10^7,在遍历时利用求每个数火柴数函数求的话时间复杂度接近会达到10^8,超时无疑,所以利用动态规划思想:cnt[i]=cnt[i/10]+l[i%10]无重复算出n以内数所需火柴数,这样时间复杂度为n

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
#define far(i,n) for(int i=0;i<n;++i)
#define fdr(i,n) for(int i=n-1;i>=0;--i)
typedef long long ll;

ll n,k;
int l[10]={6,2,5,5,4,5,6,3,7,6};
int cnt[50000010];//记录摆0~n所需的火柴数

//计算摆某个数所需的火柴数,用cnt[]数组记录时可不用这个函数
int countBar(int n)
{
    int ans=0;
    while(n)
    {
        ans+=l[n%10];
        n/=10;
    }
    return ans;
}

int main()
{
    int n,k;
    scanf("%d%d",&n,&k);
    int res=0,rest=n/k-4-countBar(n);
    if(rest<4)//A,B至少要2根火柴
    {
        printf("0");
        return 0;
    }
    //DP
    far(i,10)
        cnt[i]=l[i];
    for(int i=10;i<=n;++i)
        cnt[i]=cnt[i/10]+l[i%10];
    for(int i=0;i<=n/2;++i)
    {
        if(cnt[i]+cnt[n-i]==rest)
            ++res;
    }
    printf("%d",res);
}

 

相关文章: