您的位置:首页 > 其它

湖南省2011年程序设计大赛题解

2014-07-18 20:46 274 查看
做的时候卡傻了。贴一下标程。

A,水题:
#include <set>
#include <map>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>

using namespace std;

int cases;

int main() {
double cl = clock();

scanf("%d", &cases);
while( cases-- ) {
char a[10];
scanf("%s", a);

if( strlen(a) > 3 ) puts("3");
else {
if( ( a[0] == 'o' ) + ( a[1] == 'n' ) + ( a[2] == 'e' ) >= 2 ) puts("1");
else puts("2");
}
}

cl = clock() - cl;
fprintf(stderr, "Total Execution Time = %lf seconds\n", cl / CLOCKS_PER_SEC);

return 0;
}


B,水题,不过被卡了= =

#include <set>
#include <map>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>

using namespace std;

bool isImp7( int i ) {
if( !(i % 7) ) return true;
while(i) {
if( i % 10 == 7 ) return true;
i /= 10;
}
return false;
}

int main() {
double cl = clock();

int n, m, k;
while( scanf("%d %d %d", &n, &m, &k) == 3 && n ) {
int cnt = 0, period = 2 * n - 2;

if( n == m || m == 1 ) {
for( int i = m; ; i += period ) if( isImp7( i ) ) {
cnt++;
if( cnt == k ) {
printf("%d\n", i);
break;
}
}
}
else {
int next = 2 - m;
for( int i = m; ; swap( next, i ) ) {
next += period;

if( isImp7( i ) ) {
cnt++;
if( cnt == k ) {
printf("%d\n", i);
break;
}
}
}
}
}

cl = clock() - cl;
fprintf(stderr, "Total Execution Time = %lf seconds\n", cl / CLOCKS_PER_SEC);

return 0;
}
C,暴力匹配就行吧,数据那么弱,。。。

#include <set>
#include <map>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>

using namespace std;

int m, n;
char bigp[15][15], smallp[15][15];

int countStar( char a[15][15], int n ) {
int res = 0;
for( int i = 0; i < n; i++ ) for( int j = 0; j < n; j++ ) res += ( a[i][j] == '*' );
return res;
}

bool isValid( int x, int y ) {
return x >= 0 && x < n && y >= 0 && y < n;
}

bool isSame( int i, int j ) {
for( int x = 0; x < m; x++ ) for( int y = 0; y < m; y++ ) if( smallp[x][y] == '*' )
if( !isValid( x + i, y + j ) || bigp[x+i][y+j] != '*' ) return false;
return true;
}

bool canMatch( int k, int i, int j ) {
if( !k ) return true;
if( i == n ) return false;
if( j == n ) return canMatch( k, i + 1, -10 );

if( isSame( i, j ) ) {
for( int x = 0; x < m; x++ ) for( int y = 0; y < m; y++ ) if( smallp[x][y] == '*' ) bigp[x+i][y+j] = '.';
if( canMatch( k - 1, i, j ) ) return true;
for( int x = 0; x < m; x++ ) for( int y = 0; y < m; y++ ) if( smallp[x][y] == '*' ) bigp[x+i][y+j] = '*';
}
return canMatch( k, i, j + 1 );
}

int main() {
double cl = clock();

while( scanf("%d %d", &n, &m) == 2 && m + n ) {
for( int i = 0; i < n; i++ ) scanf("%s", bigp[i]);
for( int i = 0; i < m; i++ ) scanf("%s", smallp[i]);

int cnt1 = countStar( bigp, n );
int cnt2 = countStar( smallp, m );

if( cnt1 != cnt2 * 2 || !canMatch(2, -10, -10) ) puts("0");
else puts("1");
}

cl = clock() - cl;
fprintf(stderr, "Total Execution Time = %lf seconds\n", cl / CLOCKS_PER_SEC);

return 0;
}


D,神奇的搜索姿势,表示不会。
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>

using namespace std;

char a[15][15];
char a1[15][15];
char best[15][15];
vector<pair<int,int> > p;
int d[100];
int used[100];
int nn,n;

void search2(int x)
{
int i,j,k,xx,yy,cnt,start,dx,dy;
vector<int> q;
if (x==nn)
{
memcpy(a1,a,sizeof(a1));
memset(used,0,sizeof(used));
q.clear();
q.push_back(0);
used[0]=1;
for (i=0;i<q.size();i++)
{
xx=p[d[q[i]]].first;
yy=p[d[q[i]]].second;
for (j=0;j<nn;j++)
if ((used[j]==0)&&(abs(p[d[j]].first-xx)+abs(p[d[j]].second-yy)==1))
{
used[j]=1;
q.push_back(j);
}
}
if (q.size()!=nn) return;
memset(used,0,sizeof(used));
for (i=0;i<nn;i++)
{
used[d[i]]=1;
a1[p[d[i]].first][p[d[i]].second]='A';
}
cnt=1;
for (i=0;i<p.size();i++)
if (used[i]==0)
{
used[i]=1;
a1[p[i].first][p[i].second]='A'+cnt;
for (j=1;j<nn;j++)
{
dx=p[d[j]].first-p[d[0]].first;
dy=p[d[j]].second-p[d[0]].second;
xx=p[i].first+dx;
yy=p[i].second+dy;
for (k=0;k<p.size();k++)
if ((used[k]==0)&&(p[k].first==xx)&&(p[k].second==yy))
break;
if (k==p.size()) return;
used[k]=1;
a1[xx][yy]='A'+cnt;
}
cnt++;
}
for (i=0;i<n;i++)
for (j=0;j<n;j++)
{
if (best[i][j]<a1[i][j]) return;
if (best[i][j]>a1[i][j])
{
memcpy(best,a1,sizeof(a1));
return;
}
}
return;
}
if (x==0) start=0;
else start=d[x-1]+1;
for (i=start;i<p.size();i++)
{
d[x]=i;
search2(x+1);
}
}

void search1(int x)
{
int i,j,k,start,dx,dy,xx,yy;
vector<int> aa;
vector<int> q;
if (x==nn)
{
memcpy(a1,a,sizeof(a));
memset(used,0,sizeof(used));
for (i=0;i<nn;i++)
{
used[d[i]]=1;
a1[p[d[i]].first][p[d[i]].second]='A'+i;
}
aa.clear();
aa.push_back(d[0]);
for (i=0;i<p.size();i++)
if (used[i]==0)
{
aa.push_back(i);
used[i]=1;
a1[p[i].first][p[i].second]='A'+0;
for (j=1;j<nn;j++)
{
dx=p[d[j]].first-p[d[0]].first;
dy=p[d[j]].second-p[d[0]].second;
xx=p[i].first+dx;
yy=p[i].second+dy;
for (k=0;k<p.size();k++)
if ((used[k]==0)&&(p[k].first==xx)&&(p[k].second==yy))
{
used[k]=1;break;
}
if (k==p.size()) return;
a1[p[k].first][p[k].second]='A'+j;
}
}
memset(used,0,sizeof(used));
q.clear();
q.push_back(0);
used[0]=1;
for (i=0;i<q.size();i++)
{
xx=p[aa[q[i]]].first;
yy=p[aa[q[i]]].second;
for (j=0;j<aa.size();j++)
if ((used[j]==0)&&(abs(p[aa[j]].first-xx)+abs(p[aa[j]].second-yy)==1))
{
used[j]=1;
q.push_back(j);
}
}
if (q.size()!=aa.size()) return;
for (i=0;i<n;i++)
for (j=0;j<n;j++)
{
if (best[i][j]<a1[i][j]) return;
if (best[i][j]>a1[i][j])
{
memcpy(best,a1,sizeof(a1));
return;
}
}
return;
}
if (x==0) start=0;
else start=d[x-1]+1;
for (i=start;i<p.size();i++)
{
d[x]=i;
search1(x+1);
}
}

int main()
{
int i,j,cnt;
double cl = clock();

while (scanf("%d",&n)!=EOF)
{
if (n==0) break;
for (i=0;i<n;i++)
scanf("%s",a[i]);
cnt=0;
p.clear();
for (i=0;i<n;i++)
for (j=0;j<n;j++)
if (a[i][j]=='*')
{
p.push_back(make_pair(i,j));
cnt++;
}
memset(best,0,sizeof(best));
for (i=0;i<n;i++)
for (j=0;j<n;j++)
best[i][j]='a';
for (i=2;i<=cnt;i++)
if (cnt%i==0)
{
j=cnt/i;
if (i<=j)
{
nn=i;
search1(0);
}
else
{
nn=j;
search2(0);
}
if (best[0][0]!='a') break;
}
for (i=0;i<n;i++)
printf("%s\n",best[i]);
printf("\n");
}

cl = clock() - cl;
fprintf(stderr, "Total Execution Time = %lf seconds\n", cl / CLOCKS_PER_SEC);

return 0;
}


E,挺水的。

#include <set>
#include <map>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>

using namespace std;

int grundy( int n ) {
if( n == 1 ) return 0;
if( n & 1 ) return grundy( n/2 );
return n/2;
}

int main() {
double cl = clock();

int n;
while( scanf("%d", &n) == 1 && n ) {
printf("%s\n", grundy(n) ? "Alice" : "Bob");
}

cl = clock() - cl;
fprintf(stderr, "Total Execution Time = %lf seconds\n", cl / CLOCKS_PER_SEC);

return 0;
}
F,三维的dp,有点不好写吧。
#include <set>
#include <map>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>

using namespace std;

const double inf = 1e50;
const int NN = 10005;

int n, P;

struct info {
int p1, p2, t1, t2, w1, w2;
}A[NN];

double dp[2][101][7];

int main() {

double cl = clock();
while( scanf("%d %d", &n, &P) == 2 && n ) {
for( int i = 1; i <= n; i++ ) scanf("%d %d %d %d %d %d", &A[i].p1, &A[i].p2, &A[i].t1, &A[i].t2, &A[i].w1, &A[i].w2);

for( int i = 1; i <= 100; i++ ) for( int j = 0; j <= 6; j++ ) dp[0][i][j] = inf;
dp[0][P][0] = 0;
int cur = 1, prev = 0;
for( int k = 1; k <= n; k++ ) {
for( int i = 1; i <= 100; i++ ) for( int j = 0; j <= 6; j++ ) dp[cur][i][j] = inf;

for( int i = 1; i <= 100; i++ ) for( int j = 0; j <= 6; j++ ) if( dp[prev][i][j] < inf && i >= A[k].p1 ) {
int i1 = i + A[k].w1;
int j1 = j + A[k].w2;

if( i1 * (1 << j1) >= 100 ) i1 = 100, j1 = 0;

double r;

if( i >= A[k].p2 ) r = A[k].t2;
else r = A[k].t2 + (A[k].p2 - i + 0.) * ( A[k].t1 - A[k].t2 ) / (A[k].p2 - A[k].p1);

dp[cur][i1][j1] = min( dp[cur][i1][j1], r + dp[prev][i][j] );

}

for( int j = 6; j > 0; j-- ) for( int i = 1; i <= 100; i++ ) if( dp[cur][i][j] < inf ) {
int i1 = min( i * 2, 100 );
int j1 = j - 1;
dp[cur][i1][j1] = min( dp[cur][i1][j1], dp[cur][i][j] );
}

swap( cur, prev );
}
double res = inf;
for( int j = 6; j >= 0; j-- ) for( int i = 1; i <= 100; i++ ) res = min( res, dp[prev][i][j] );
if(res > inf/2) printf("Impossible\n");
else printf("%.2lf\n", res + 1e-11);
}

cl = clock() - cl;
fprintf(stderr, "Total Execution Time = %lf seconds\n", cl / CLOCKS_PER_SEC);

return 0;
}


G,没懂。
#include <set>
#include <map>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>

using namespace std;

const int NN = 205;
const int inf = 100000000;
const int MOD = 1000000009;

int n, A[NN][NN], val[NN][NN], dp[NN][NN], state[NN][NN], caseno;

int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};

int isvalid( int x, int y ) {
return x >= 0 && x < n && y >= 0 && y < n && x <= y;
}

int call( int i, int j ) {
if( i == 0 && j == n - 1 ) return 1;

int &ret = dp[i][j];
int &st = state[i][j];

if( st == caseno ) return ret;
st = caseno;

ret = 0;

for( int k = 0; k < 4; k++ ) {
int x = i + dx[k];
int y = j + dy[k];

if( isvalid( x, y ) && val[x][y] + A[i][j] == val[i][j] ) ret = ( ret + call( x, y ) ) % MOD;
}

return ret;
}

int main() {
double cl = clock();

while( scanf("%d", &n) == 1 && n ) {
for( int i = n - 1; i >= 0; i-- ) for( int j = 0; j < n; j++ ) scanf("%d", &A[j][i]);

for( int i = 0; i < n; i++ ) for( int j = i + 1; j < n; j++ ) A[i][j] += A[j][i];

for( int i = 0; i < n; i++ ) for( int j = i; j < n; j++ ) val[i][j] = inf;

queue <int> Q;
Q.push( 0 );
Q.push( n - 1 );
val[0][n - 1] = A[0][n - 1];

while( !Q.empty() ) {
int u = Q.front(); Q.pop();
int v = Q.front(); Q.pop();

for( int k = 0; k < 4; k++ ) {
int x = u + dx[k];
int y = v + dy[k];

if( isvalid( x, y ) && val[x][y] > val[u][v] + A[x][y] ) {
val[x][y] = val[u][v] + A[x][y];
Q.push(x);
Q.push(y);
}
}
}
int mn = inf, res = 0;
for( int i = 0; i < n; i++ ) mn = min( mn, val[i][i] );

++caseno;

for( int i = 0; i < n; i++ ) if( val[i][i] == mn ) res = ( res + call( i, i ) ) % MOD;

printf("%d\n", res);
}

cl = clock() - cl;
fprintf(stderr, "Total Execution Time = %lf seconds\n", cl / CLOCKS_PER_SEC);

return 0;
}


H,计算几何,不会。

/*
Author       :	Jan
Problem Name :
Algorithm    :
Complexity   :
*/

#include <set>
#include <map>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>

using namespace std;

const double eps = 1e-9;
const double pi = 2 * acos( 0.0 );

inline bool eq(double a, double b) { return fabs( a - b ) < eps; }
inline bool eq2(double a, double b) { return fabs( a - b ) < 1e-7; }
struct point {
double x, y;
point() {}
point( double xx, double yy ) { x = xx, y = yy; }
bool operator < ( const point &b ) const {
if( eq( x, b.x ) ) {
if( eq( y, b.y ) ) return false;
return y < b.y;
}
return x < b.x;
}
};
struct line {
double a, b, c;
line() {}
line( point p1,point p2 ) {
a=p1.y-p2.y;
b=p2.x-p1.x;
c=p1.x*p2.y-p2.x*p1.y;
}
};
struct circle {
point center;
double r;
circle() {}
circle( point P, double rr ) { center = P; r = rr; }
};
struct segment {
point A, B;
segment() {}
segment( point P1, point P2 ) { A = P1, B = P2; }
};
inline double Distance( point a, point b ) {
return sqrt( ( a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y ) );
}
inline double Distance( point P, line L ) {
return fabs( L.a * P.x + L.b * P.y + L.c ) / sqrt( L.a * L.a + L.b * L.b );
}
inline double isleft( point p0, point p1, point p2 ) {
return( ( p1.x - p0.x ) * ( p2.y - p0.y ) - ( p2.x - p0.x ) * ( p1.y - p0.y ) );
}
inline bool intersection( line L1, line L2, point &p ) {
double det = L1.a * L2.b - L1.b * L2.a;
if( eq ( det, 0 ) ) return false;
p.x = ( L1.b * L2.c - L2.b * L1.c ) / det;
p.y = ( L1.c * L2.a - L2.c * L1.a ) / det;
return true;
}
inline bool intersection( segment L1, segment L2, point &p ) {
if( !intersection( line( L1.A, L1.B ), line( L2.A, L2.B ), p) ) return false;
return(eq(Distance(L1.A,p)+Distance(L1.B,p),Distance(L1.A,L1.B)) &&
eq(Distance(L2.A,p)+Distance(L2.B,p),Distance(L2.A,L2.B)));
}
inline line findPerpendicularLine( line L, point P ) {
line res;
res.a = L.b, res.b = -L.a;
res.c = -res.a * P.x - res.b * P.y;
return res;
}
inline double Distance( point P, segment S ) {
line L1 = line( S.A, S.B ), L2;
point P1;
L2 = findPerpendicularLine( L1, P );
if( intersection( L1, L2, P1 ) )
if( eq2 ( Distance( S.A, P1 ) + Distance( S.B, P1 ), Distance( S.A, S.B ) ) )
return Distance(P,L1);
return min ( Distance( S.A, P), Distance( S.B, P) );
}

const int MAX_LINE = 25;
const int MAX_CIRCLE = 25;

int n, m, L, W, sv[MAX_LINE*MAX_LINE];
segment S[MAX_LINE];
point P[MAX_LINE*MAX_LINE];
circle C[MAX_CIRCLE];

map <point, int> M;
set <point> adjLine[MAX_LINE];
vector <int> adj[MAX_LINE*MAX_LINE];
vector <bool> taken[MAX_LINE*MAX_LINE];
vector <double> res[MAX_CIRCLE];

int getId( point p ) {
if( M.find(p) == M.end() ) {
int N = M.size();
M[p] = N;
adj
.clear();
P
= p;
}
return M[p];
}

double areaPolygon( int sv[], int n ) {
double area = 0;
for( int i = 0, j = n - 1; i < n; j = i++ ) area += P[sv[j]].x * P[sv[i]].y - P[sv[j]].y * P[sv[i]].x;
return fabs(area)/2;
}

bool intersect( circle C, int sv[], int k ) {
vector <point> V;

for( int i = 0; i <= k; i++ ) {
V.push_back( P[ sv[i] ] );
V[i].x -= C.center.x;
V[i].y -= C.center.y;
}
bool flag = true;
for( int i = 0; i < k; i++ ) {
double dsq = V[i].x*V[i].x + V[i].y*V[i].y;
double rsq = C.r * C.r;
if( dsq + eps < rsq ) return true;
if( dsq > rsq + eps ) flag = false;
}
if( flag ) return true;
flag = true;
for( int i = 0; i < k; i++ ) if( isleft( V[i], V[i+1], point(0, 0) ) < -eps ) {
flag = false;
break;
}
if( flag ) return true;

// for all other cases, at least one edge of the polygon should intersect with the circle
for( int i = 0; i < k; i++ ) if( Distance( point(0, 0), segment( V[i], V[i+1] ) ) + eps < C.r ) return true;
return false;
}

void makeChain( int k ) {
if( sv[k-1] == sv[0] ) {
// full chain
double area = areaPolygon( sv, k - 1 );

for( int i = 0; i < m; i++ ) if( intersect( C[i], sv, k - 1 ) ) res[i].push_back( area );
return;
}
int u = sv[k-1], j = -1;
for( int i = 0; i < adj[u].size(); i++ ) {
int v = adj[u][i];
if( v == sv[k-2] ) continue;
if( isleft( P[sv[k-2]], P[sv[k-1]], P[v] ) > eps ) {
if( j == -1 || isleft( P[ sv[k-1] ], P[  adj[u][j] ], P[ v ] ) > eps ) j = i;
}
}
if( j == -1 ) return;
taken[u][j] = true;
sv[k] = adj[u][j];
makeChain( k + 1 );
}

int main() {
//freopen("h1.in", "r", stdin);
//freopen("h1jan.ans", "w", stdout);

double cl = clock();

while( scanf("%d %d %d %d", &n, &m, &L, &W) == 4 && n ) {
for( int i = 0; i < n; i++ ) scanf("%lf %lf %lf %lf", &S[i].A.x, &S[i].A.y, &S[i].B.x, &S[i].B.y);
for( int i = 0; i < m; i++ ) scanf("%lf %lf %lf", &C[i].center.x, &C[i].center.y, &C[i].r);

S[n++] = segment( point( 0, 0 ), point( L, 0 ) );
S[n++] = segment( point( 0, 0 ), point( 0, W ) );
S[n++] = segment( point( 0, W ), point( L, W ) );
S[n++] = segment( point( L, 0 ), point( L, W ) );

for( int i = 0; i < n; i++ ) adjLine[i].clear();
for( int i = 0; i < m; i++ ) res[i].clear();

M.clear();
for( int i = 0; i < n; i++ ) {
for( int j = i + 1; j < n; j++ ) {
point p;
if( intersection( S[i], S[j], p ) ) {
int x = getId(p);
adjLine[i].insert(p);
adjLine[j].insert(p);
}
}
}

for( int i = 0; i < n; i++ ) {
vector <point> V;
for( set <point> ::iterator s = adjLine[i].begin(); s != adjLine[i].end(); s++ ) V.push_back( *s );

for( int j = 0; j < V.size() - 1; j++ ) {
adj[ M[ V[j] ] ].push_back( M[ V[j + 1] ] );
adj[ M[ V[j + 1] ] ].push_back( M[ V[j] ] );
}
}

for( int i = 0; i < M.size(); i++ ) {
taken[i].clear();
for( int j = 0; j < adj[i].size(); j++ ) taken[i].push_back(false);
}

for( int i = 0; i < M.size(); i++ ) {
for( int j = 0; j < adj[i].size(); j++ ) if( !taken[i][j] ) {
taken[i][j] = true;
sv[0] = i;
sv[1] = adj[i][j];

makeChain( 2 );
}
}
for( int i = 0; i < m; i++ ) {
printf("%d", res[i].size());
sort( res[i].begin(), res[i].end() );
for( int j = 0; j < res[i].size(); j++ ) printf(" %.2lf", res[i][j] + 1e-7);
puts("");
}
puts("");
}

cl = clock() - cl;
fprintf(stderr, "Total Execution Time = %lf seconds\n", cl / CLOCKS_PER_SEC);

return 0;
}


I,感觉是快速幂加速的dp;

#include <set>
#include <map>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long i64;

const int MOD = 1000000009;
const int NN = 256;

// recurrence: f(n, k) = f(n-k, k) + f(n-k, k-1) * 4 + f(n-k, k-2) * 6 + f(n-k, k-3) * 4 + f(n-k, k-4)

int n, k, N, pos[18][18];;
int base[NN][NN], res[NN][NN], temp[NN][NN];

int multiply( int A[NN][NN], int B[NN][NN], int C[NN][NN] ) {
for( int i = 0; i < N; i++ ) for( int j = 0; j < N; j++ ) {
temp[i][j] = 0;
for( int k = 0; k < N; k++ ) if( A[i][k] && B[k][j] ) temp[i][j] = ( temp[i][j] + A[i][k] * (i64)B[k][j] ) % MOD;
}
for( int i = 0; i < N; i++ ) for( int j = 0; j < N; j++ ) C[i][j] = temp[i][j];
}

void buildBase() {
for( int i = 0; i < N; i++ ) {
for( int j = 0; j < N; j++ ) base[i][j] = res[i][j] = 0;
res[i][i] = 1;
}
// build base
int x = 0;
for( int j = k; j >= 1; j-- ) for( int i = k + 1; i > 1; i-- ) {
if( pos[i][j] == -1 ) {
int p = i - j, q = j;
if( p >= 1 ) {
assert( pos[p][q] > -1 ); base[x][ pos[p][q] ] = 1;
q--;
if( q > 0 ) {
assert( pos[p][q] > -1 ); base[x][ pos[p][q] ] = 4;
q--;
if( q > 0 ) {
assert( pos[p][q] > -1 ); base[x][ pos[p][q] ] = 6;
q--;
if( q > 0 ) {
assert( pos[p][q] > -1 ); base[x][ pos[p][q] ] = 4;
q--;
if( q > 0 ) {
assert( pos[p][q] > -1 ); base[x][ pos[p][q] ] = 1;
}
}
}
}
}
}
else base[x][ pos[i][j] ] = 1;
x++;
}
}

int solve() {
int dp[20][17] = {0};

dp[0][0] = 1;
for( int i = 1; i < 20; i++ ) {
for( int j = 1; j <= k; j++ ) {
int p = i - j, q = j;
if( p >= 0 && q >= 0 ) dp[i][j] = (dp[i][j] + dp[p][q]) % MOD;
q--; if( p >= 0 && q >= 0 ) dp[i][j] = (dp[i][j] + 4 * (i64) dp[p][q]) % MOD;
q--; if( p >= 0 && q >= 0 ) dp[i][j] = (dp[i][j] + 6 * (i64) dp[p][q]) % MOD;
q--; if( p >= 0 && q >= 0 ) dp[i][j] = (dp[i][j] + 4 * (i64) dp[p][q]) % MOD;
q--; if( p >= 0 && q >= 0 ) dp[i][j] = (dp[i][j] + dp[p][q]) % MOD;
}
}
if( n < 20 ) {
int r = 0;
for( int i = 1; i <= k; i++ ) r = ( r + dp
[i] ) % MOD;
return r;
}
int f[NN] = {0}, f1[NN] = {0};
N = 0;
memset( pos, -1, sizeof(pos) );
for( int i = k; i >= 1; i-- ) for( int j = k; j >= 1; j-- ) {
f
= dp[j][i];
pos[j][i] = N++;
}

buildBase();

int p = n - k;

while( p ) {
if( p & 1 ) multiply( res, base, res );
multiply( base, base, base );
p >>= 1;
}

for( int i = 0; i < N; i++ ) for( int k = 0; k < N; k++ ) if( f[k] && res[i][k] ) f1[i] = (f1[i] + res[i][k] * (i64)f[k]) % MOD;

int r = 0;
for( int i = 0; i < N; i += k ) r = ( r + f1[i] ) % MOD;
return r;
}

int main() {
double cl = clock();

while( scanf("%d %d", &n, &k) == 2 && n ) {
printf("%d\n", solve());
}

cl = clock() - cl;
fprintf(stderr, "Total Execution Time = %lf seconds\n", cl / CLOCKS_PER_SEC);

return 0;
}
J,尼玛扑克的范围不一定啊。那就是说。。。要算很大的数了。。。暴力不行了。。用了fft。没看懂这个神奇的算法,。。。

#include<cmath>
#include<cstring>
#include<cstdio>
#include<cassert>
#include<algorithm>
#include <ctime>

#define rept(i,n) for(int i = 0; i < (n); i++)

#define PI 3.14159265358979323846264338327950288

using namespace std;

struct pdd
{
double x,y;
pdd():x(0),y(0) {}
pdd(double _x,double _y):x(_x),y(_y) {}
};
inline pdd operator +(const pdd &a,const pdd &b)
{
return pdd(a.x+b.x,a.y+b.y);
}
inline pdd operator -(const pdd &a,const pdd &b)
{
return pdd(a.x-b.x,a.y-b.y);
}
inline pdd operator *(const pdd &a,const pdd &b)
{
return pdd(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);
}
inline pdd operator /(const pdd &a,const double &b)
{
return pdd(a.x/b,a.y/b);
}
inline pdd conj(const pdd &a)
{
return pdd(a.x,-a.y);
}

const int maxn = 300000;
struct FFT {
int n;
int SN;
int rv[1<<18];
pdd w[1<<18];

void fft(pdd *a, bool inv)
{
int cc=0;
rept(i,30) if (n&1<<i) cc=i;
if (cc!=SN)
{
SN=cc;
rv[0]=0; rv[1]=1;
for(int st = 1; st <= SN-1; st++)
{
int k=1<<st;
rept(i,k)
{
rv[i+(1<<st)]=rv[i]*2+1;
rv[i]*=2;
}
}
rept(i,1<<SN) w[i]=pdd(cos(2.0*PI*i/n),sin(2.0*PI*i/n));
}
rept(i,n) if (rv[i]<=i) swap(a[i],a[rv[i]]);
for (int st=2;st<=n;st*=2)
{
int d=n/st,o=st/2;
for (int i=0;i<n;i+=st)
{
for (int j=0;j<o;++j)
{
pdd u=a[i+j],v=a[i+j+o]*(inv?conj(w[j*d]):w[j*d]);
a[i+j]=u+v;
a[i+j+o]=u-v;
}
}
}
if (inv) rept(i,n) a[i]=a[i]/n;
}

void Multi(long long* A, int NA, long long* B, int NB, long long* C, pdd* tA, pdd* tB) {
SN = -1;
n = 1;
while(n < NA + NB) n *= 2;
n *= 2;

for(int i = 0; i < n; i++) {
tA[i] = (i < NA ? pdd(A[i], 0) : pdd(0, 0));
tB[i] = (i < NB ? pdd(B[i], 0) : pdd(0, 0));
}

fft(tA, 0);
fft(tB, 0);
for(int i = 0; i < n; i++)
tA[i] = tA[i] * tB[i];
fft(tA, 1);

for(int i = 0; i < n; i++)
C[i] = (long long)(tA[i].x + 0.5);
}
};

FFT fft;

int vis[100000];

void sieve(int n) {
int m = (int)sqrt(n+0.5);
memset(vis, 0, sizeof(vis));
for(int i = 2; i <= m; i++) if(!vis[i])
for(int j = i*i; j <= n; j+=i) vis[j] = 1;
}

long long poly[7][maxn];
pdd tA[maxn], tB[maxn];

int getSuit(char s) {
if(s == 'S') return 0;
if(s == 'H') return 1;
if(s == 'C') return 2;
if(s == 'D') return 3;
}

int main() {
int a, p, c;

double cl = clock();

sieve(50000);
while(scanf("%d%d%d", &a, &p, &c) == 3 && p) {
for(int i = 0; i < p; i++) {
int v = 0;
if(i >= 4 && vis[i]) v = 1;
poly[0][i] = poly[1][i] = poly[2][i] = poly[3][i] = v;
}
for(int i = 0; i < c; i++) {
char card[9];
scanf("%s", card);
int len = strlen(card);
int suit = getSuit(card[len-1]);
int rank;
card[len-1] = '\0';
sscanf(card, "%d", &rank);
assert(rank >= 4 && vis[rank]);
poly[suit][rank] = 0;
}
fft.Multi(poly[0], p, poly[1], p, poly[4], tA, tB);
fft.Multi(poly[2], p, poly[3], p, poly[5], tA, tB);
fft.Multi(poly[4], p, poly[5], p, poly[6], tA, tB);
for(int i = a; i <= p; i++)
printf("%d\n", poly[6][i] % 1000000); // linuxϸijÉ%lld
printf("\n");
}

cl = clock() - cl;
fprintf(stderr, "Total Execution Time = %lf seconds\n", cl / CLOCKS_PER_SEC);

return 0;
}
K,线段树傻逼题,没时间呢。其实我线段树一点都不熟。。但是知道怎么做。。
#include <set>
#include <map>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>

using namespace std;

const int NN = 1 << 18;
const int inf = 1000000000;

int n, q, A[NN], pos[NN], test, T[NN], C[50], update[NN];

void makeTree( int idx, int low, int high ) {
if( low == high ) {
T[idx] = A[low];
pos[low] = idx;
update[idx] = 0;
return;
}

int mid = (low + high) >> 1;
makeTree( idx << 1, low, mid );
makeTree( ( idx << 1 ) | 1, mid + 1, high );

T[idx] = min( T[idx << 1], T[(idx << 1 ) | 1] );
}

int queryTree( int idx, int low, int high, int x, int y ) {
if( x <= low && high <= y ) return T[idx];
int res = inf, mid = (low + high) >> 1;
if( x <= mid ) res = queryTree( idx << 1, low, mid, x, y );
if( y > mid  ) res = min( res, queryTree( ( idx << 1 ) | 1, mid + 1, high, x, y ) );
return res;
}

int main() {
double cl = clock();

while( scanf("%d %d", &n, &q) == 2 && n ) {
for( int i = 1; i <= n; i++ ) scanf("%d", &A[i]);

makeTree( 1, 1, n );
test = 0;

while( q-- ) {
char a[40];
scanf("%s", a);

if( a[0] == 'q' ) {
int x, y;
sscanf( a + 6, "%d , %d", &x, &y );
printf("%d\n", queryTree( 1, 1, n, x, y ));
}
else {
char *p = strtok( a + 6, "," );
int x = 0;
while( p ) {
sscanf( p, "%d", &C[x] );
p = strtok( NULL, "," );
x++;
}
int s = T[ pos[ C[0] ] ];
for( int i = 1; i < x; i++ ) T[ pos[ C[i-1] ] ] = T[ pos[ C[i] ] ];
T[ pos[ C[x - 1] ] ] = s;

++test;

queue <int> Q;
for( int i = 0; i < x; i++ ) {
int idx = pos[ C[i] ] >> 1;
if( update[idx] < test ) {
update[idx] = test;
Q.push( idx );
}
}

while( !Q.empty() ) {
int idx = Q.front(); Q.pop();

T[idx] = min( T[idx << 1], T[(idx << 1 ) | 1] );
if( idx > 1 ) {
idx >>= 1;
if( update[idx] < test ) {
update[idx] = test;
Q.push( idx );
}
}
}
}
}
}

cl = clock() - cl;
fprintf(stderr, "Total Execution Time = %lf seconds\n", cl / CLOCKS_PER_SEC);

return 0;
}


学姐告诉我被虐是很正常的,要有一个良好的心态去对待各种比赛。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐