Description [title]
Alice wants to get a positive integer of length n-$ $ sequence, the sequence is not more than $ m $, and this $ $ n-number and a multiple of $ p $.
Alice is also desirable, that $ $ n-number, at least a number is a prime number.
Alice wanted to know how many sequences satisfy her request.
[Input Format]
Row of three numbers, $ n, m, p $.
[Output format]
A sequence number of a line number, Alice meet the requirements. Since many possible sequences satisfy the conditions, the output of the modulo $ $ 20,170,408.
[Sample]
Sample input
353
sample output
33
[Note] with the data range
For $ 20 \% $ data, $ 1 \ le n \ le 100,1 \ le m \ le 100 $.
For $ 50 \% $ data, $ 1 \ le m \ le 100 $.
For $ 80 \% $ data, $ 1 \ le m \ le 10 ^ 6 $.
For $ 100 \% $ data, $ 1 \ le n \ le 10 ^ 9,1 \ le m \ le 2 \ times 10 ^ 7,1 \ le p \ le 100 $.
【answer】
Provided $ f [i] [j] [0/1] $ $ I $ denotes the number of the front, and at $ mod \ p $ $ J $ meaning, if taking the number of prime numbers embodiment.
After the transfer list with a quick power or polynomial matrix can be optimized.
[Code]
#include<bits/stdc++.h> const int mod=20170408; int n,m,p,pr[20000010],tot; bool flag[20000010]; struct Poly { int a[110]; inline friend Poly operator + ( const Poly &p1,const Poly &p2 ) { Poly p3;memset(p3.a,0,sizeof(p3.a)); for ( int i=0;i<p;i++ ) p3.a[i]=(p1.a[i]+p2.a[i])%mod; return p3; } inline friend Poly operator - ( const Poly &p1,const Poly &p2 ) { Poly p3;memset(p3.a,0,sizeof(p3.a)); for ( int i=0;i<p;i++ ) p3.a[i]=(p1.a[i]-p2.a[i]+mod)%mod; return p3; } inline friend Poly operator * ( const Poly &p1,const Poly &p2 ) { Poly p3;memset(p3.a,0,sizeof(p3.a)); for ( int i=0;i<p;i++ ) for ( int j=0;j<p;j++ ) p3.a[(i+j)%p]=(p3.a[(i+j)%p]+1LL*p1.a[i]*p2.a[j])%mod; return p3; } inline friend Poly operator ^ ( Poly p,int n ) { Poly res;memset(res.a,0,sizeof(res.a));res.a[0]=1; for ( ;n;n>>=1,p=p*p ) if ( n&1 ) res=res*p; return res; } }A,B; signed main() { scanf("%d%d%d",&n,&m,&p); flag[1]=true; for ( int i=2;i<=m;i++ ) { if ( !flag[i] ) pr[++tot]=i; for ( int j=1;j<=tot and pr[j]*i<=m;j++ ) { flag[i*pr[j]]=true; if ( !(j%i) ) break; } } for ( int i=1;i<=m;i++ ) A.a[i%p]++,B.a[i%p]+=flag[i]; for ( int i=0;i<p;i++ ) A.a[i]%=mod,B.a[i]%=mod; printf("%d\n",((A^n)-(B^n)).a[0]); }