很简单的一道欧拉函数相关的题。。
但是我实在是对数论不熟,各种小错导致调了很久 T^T
题目链接:http://codeforces.com/contest/345/problem/C
通过这道题学习了欧拉函数的相关知识
逆元可以利用扩展欧几里德或欧拉函数求得(p为质数):
1).扩展欧几里德:b*x+p*y=1 有解,x就是所求
#include<cstdio> #include<iostream> #include<sstream> #include<cstdlib> #include<cstring> #include<string> #include<climits> #include<cmath> #include<algorithm> #include<queue> #include<vector> #include<stack> #include<set> #include<map> #define INF 0x3f3f3f3f #define eps 1e-8 using namespace std; const int MAXN=1100; const int MAXM=110000; int cot[10][1<<10]; long long d[MAXN][MAXN]; long long m[MAXM]; const long long mod=1000000007; int f(int x) { int tot=0,ret=0; while(x) { tot++; int y=x%10; x/=10; if(y==4) { ret=(ret<<1)^1; } else if(y==7) { ret<<=1; } else return 0; } if(tot) { cot[tot][ret]++; if(cot[tot][ret]>1) { return 1; } } return 0; } long long pown(int x,int k) { long long ans=1LL; long long ret=x; while(k) { if(k&1) { ans=(ans*ret)%mod; } ret=(ret*ret)%mod; k>>=1; } return ans; } long long C(int n, int k) { if(n<k) { return 0LL; } long long ans=m[n]; ans=(ans*pown(m[n-k],mod-2))%mod; ans=(ans*pown(m[k],mod-2))%mod; return ans; } int main() { int n,k; m[0]=1; for(int i=1; i<MAXM; i++) { m[i]=(m[i-1]*i)%mod; } while(scanf("%d%d",&n,&k)==2) { memset(cot,0,sizeof(cot)); int ret=0; for(int i=0; i<n; i++) { int x; scanf("%d",&x); ret+=f(x); } n-=ret; if(n<k) { puts("0"); continue; } long long ans=0LL; int tot=0; memset(d,0,sizeof(d)); d[0][0]=1LL; for(int i=1; i<10; i++) { for(int j=0; j<(1<<i); j++) { if(cot[i][j]) { tot++; for(int num=tot; num; num--) { d[tot][num]=(d[tot-1][num]+d[tot-1][num-1]*cot[i][j])%mod; } d[tot][0]=d[tot-1][0]; } } } for(int j=0; (j<=k)&&(j<=tot); j++) { ans+=(d[tot][j]*C(n-tot,k-j))%mod; ans%=mod; } printf("%I64d\n",ans); } return 0; }