51Nod - 1284 数位DP或容斥原理
给出一个数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 Input10Sample 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); }