51Nod - 1284 数位DP或容斥原理

51Nod - 1284

  给出一个数N,求1至N中,有多少个数不是2 3 5 7的倍数。 例如N = 10,只有1不是2 3 5 7的倍数。

Input输入1个数N(1 <= N <= 10^18)。Output输出不是2 3 5 7的倍数的数共有多少。Sample Input
10
Sample Output
1

    首先,我承认这是个容斥原理的水题,容斥代码及长相不咋样的文氏图(我是一个不会旋转图片的菜鸡,下载了看吧);

     看不懂代码自己补离散数学(当然高中数学竞赛教程中也有讲),我这个数竞菜鸡就不讲了;


#include <iostream>
using  namespace  std;
int  main(){
    unsigned  long  long  n;
              while(cin>>n){
                                  cout << n-(n/2+n/3+n/5+n/7-n/6-n/10-n/14-n/15-n/21-n/35+n/30+n/42+n/70+n/105-n/210) << endl;
                }
                return  0;

}

刚刚学完数位dp,看见10的好大次方就想用数位DP(对不起数竞老师,给数学系抹黑了);

#include<bits\stdc++.h>
using namespace std;
long long dp[20][2][3][5][7];
int dig[20];
long long dfs(int s,int t2,int t3,int t5,int t7,bool u){
	if(s==0){
		if(t2==0||t3==0||t5==0||t7==0)return 0;
		else return 1;
	}
	if(!u&&dp[s][t2][t3][t5][t7]!=-1)return dp[s][t2][t3][t5][t7];
	long long ans=0;
	int t=u?dig[s]:9;
	for(int i=0;i<=t;i++){
		ans+=dfs(s-1,(10*t2+i)%2,(10*t3+i)%3,(10*t5+i)%5,(10*t7+i)%7,u&&(i==t));
	}
	if(!u)dp[s][t2][t3][t5][t7]=ans;
	return ans;
}
int cal(long long n){
	int s=0;
	while(n!=0){
		dig[++s]=n%10;
		n/=10;
	}
	printf("%lld",dfs(s,0,0,0,0,true));
}
int main() {
	long long n;
	memset(dp,-1,sizeof(dp));
	scanf("%lld",&n);
	cal(n);
}

posted @ 2018-02-26 20:08  可爱如我  阅读(140)  评论(0编辑  收藏  举报