prow2012-A3-0017
从 Trac 迁移的文章
这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。
原文章内容如下:
题意是说,一个正多边形有N个点,每个点有2个属性值(1..P,1..Q),相邻两个点必须有一种属性相同。
给出8个点的属性,求样的正多边形数量。
首先写出DP方程,f[i,0,0]表示到第i个,跟末尾的参照两个属性都不相同的方案数,f[i,0,1]表示第二个属性相同,f[i,1,0],f[i,1,1]依次类推。
转移的方法就是右乘上这个矩阵:
{{{
ULL mm[6][6] = {
{(P+Q-3)%MOD,1,1,0},
{(Q-1)%MOD,(P-1)%MOD,0,1},
{(P-1)%MOD,0,(Q-1)%MOD,1},
{0,(P-1)%MOD,(Q-1)%MOD,1},
};
}}}
注意所有数字都要long long,WA过;注意输入的位置可能相同,需要特判,WA过。
{{{
#include <vector>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <set>
#include <map>
#include <sstream>
#include <string>
#include <math.h>
using namespace std;
typedef unsigned long long ULL;
struct Mat {
ULL M[6][6];
void clear() {
memset(M, 0, sizeof (M));
}
};
int N, M, K;
int MOD = 1234567890;
void copy(Mat &A, Mat &B) {
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
A.M[i][j] = B.M[i][j];
}
void Mmut(Mat &A, Mat &B) {
Mat C;
int i, j, k;
C.clear();
for (i = 0; i < N; i++)
for (j = 0; j < N; j++)
if (A.M[i][j]) {
for (k = 0; k < N; k++)
{
C.M[i][k] += A.M[i][j] * B.M[j][k];
C.M[i][k]%=MOD;
}
}
copy(A, C);
}
ULL pos[10],p[10],q[10];
int order[10];
bool cmp(int i,int j){
return pos[i]<pos[j];
}
int main(){
N = 4;
ULL L,P,Q;
long long len;
int i,j,k;
while(cin>>L>>P>>Q){
ULL mm[6][6] = {
{(P+Q-3)%MOD,1,1,0},
{(Q-1)%MOD,(P-1)%MOD,0,1},
{(P-1)%MOD,0,(Q-1)%MOD,1},
{0,(P-1)%MOD,(Q-1)%MOD,1},
};
if (P+Q-3<0) mm[0][0] = 0;
Mat stand;
stand.clear();
memcpy(stand.M,mm,sizeof(mm));
for (i=0;i<8;i++){
cin>>pos[i]>>p[i]>>q[i];
pos[i]--;
order[i] = i;
}
sort(order,order+8,cmp);
ULL ans = 1;
for (i=0;i<8;i++){
if (i==7) len = (pos[order[0]]+L-pos[order[i]])%L-1;
else len = (pos[order[i+1]]-pos[order[i]])-1;
if (len==-1){
if (p[order[i]]!=p[order[(i+1)%8]]||
q[order[i]]!=q[order[(i+1)%8]])
{
ans = 0;
break;
}else continue;
}
Mat R,res;
R.clear(),res.clear();
for (j=0;j<N;j++)
res.M[j][j] = 1;
copy(R,stand);
while(len){
if (len&1) Mmut(res,R);
Mmut(R,R);
len>>=1;
}
Mat init;
init.clear();
bool a = (p[order[i]]==p[(order[(i+1)%8])]);
bool b = (q[order[i]]==q[(order[(i+1)%8])]);
if (a&&b) init.M[0][3] = 1;
else if (b) init.M[0][1] = 1;
else if (a) init.M[0][2] = 1;
else init.M[0][0] = 1;
Mmut(init,res);
ULL tmp = init.M[0][1]+init.M[0][2]+init.M[0][3];
tmp%=MOD;
ans*=tmp;
ans%=MOD;
//cout<<init.M[0][1]+init.M[0][2]+init.M[0][3]<<" "<<i<<endl;
}
cout<<ans<<endl;
}
}
}}}
题意是说,一个正多边形有N个点,每个点有2个属性值(1..P,1..Q),相邻两个点必须有一种属性相同。
给出8个点的属性,求样的正多边形数量。
首先写出DP方程,f[i,0,0]表示到第i个,跟末尾的参照两个属性都不相同的方案数,f[i,0,1]表示第二个属性相同,f[i,1,0],f[i,1,1]依次类推。
转移的方法就是右乘上这个矩阵:
ULL mm[6][6] = {
{(P+Q-3)%MOD,1,1,0},
{(Q-1)%MOD,(P-1)%MOD,0,1},
{(P-1)%MOD,0,(Q-1)%MOD,1},
{0,(P-1)%MOD,(Q-1)%MOD,1},
};
注意所有数字都要long long,WA过;注意输入的位置可能相同,需要特判,WA过。
#include <vector>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <set>
#include <map>
#include <sstream>
#include <string>
#include <math.h>
using namespace std;
typedef unsigned long long ULL;
struct Mat {
ULL M[6][6];
void clear() {
memset(M, 0, sizeof (M));
}
};
int N, M, K;
int MOD = 1234567890;
void copy(Mat &A, Mat &B) {
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
A.M[i][j] = B.M[i][j];
}
void Mmut(Mat &A, Mat &B) {
Mat C;
int i, j, k;
C.clear();
for (i = 0; i < N; i++)
for (j = 0; j < N; j++)
if (A.M[i][j]) {
for (k = 0; k < N; k++)
{
C.M[i][k] += A.M[i][j] * B.M[j][k];
C.M[i][k]%=MOD;
}
}
copy(A, C);
}
ULL pos[10],p[10],q[10];
int order[10];
bool cmp(int i,int j){
return pos[i]<pos[j];
}
int main(){
N = 4;
ULL L,P,Q;
long long len;
int i,j,k;
while(cin>>L>>P>>Q){
ULL mm[6][6] = {
{(P+Q-3)%MOD,1,1,0},
{(Q-1)%MOD,(P-1)%MOD,0,1},
{(P-1)%MOD,0,(Q-1)%MOD,1},
{0,(P-1)%MOD,(Q-1)%MOD,1},
};
if (P+Q-3<0) mm[0][0] = 0;
Mat stand;
stand.clear();
memcpy(stand.M,mm,sizeof(mm));
for (i=0;i<8;i++){
cin>>pos[i]>>p[i]>>q[i];
pos[i]--;
order[i] = i;
}
sort(order,order+8,cmp);
ULL ans = 1;
for (i=0;i<8;i++){
if (i==7) len = (pos[order[0]]+L-pos[order[i]])%L-1;
else len = (pos[order[i+1]]-pos[order[i]])-1;
if (len==-1){
if (p[order[i]]!=p[order[(i+1)%8]]||
q[order[i]]!=q[order[(i+1)%8]])
{
ans = 0;
break;
}else continue;
}
Mat R,res;
R.clear(),res.clear();
for (j=0;j<N;j++)
res.M[j][j] = 1;
copy(R,stand);
while(len){
if (len&1) Mmut(res,R);
Mmut(R,R);
len>>=1;
}
Mat init;
init.clear();
bool a = (p[order[i]]==p[(order[(i+1)%8])]);
bool b = (q[order[i]]==q[(order[(i+1)%8])]);
if (a&&b) init.M[0][3] = 1;
else if (b) init.M[0][1] = 1;
else if (a) init.M[0][2] = 1;
else init.M[0][0] = 1;
Mmut(init,res);
ULL tmp = init.M[0][1]+init.M[0][2]+init.M[0][3];
tmp%=MOD;
ans*=tmp;
ans%=MOD;
//cout<<init.M[0][1]+init.M[0][2]+init.M[0][3]<<" "<<i<<endl;
}
cout<<ans<<endl;
}
}