lightOJ 1172 Krypton Number System(矩阵+DP)
题目链接:http://lightoj.com/volume_showproblem.php?problem=1172
题意:一个n进制(2<=n<=6)的数字,满足以下条件:(1)至少包含两位且不以0开头,比如012是不行的;(2)相邻数字不同;(3)定义这个数字x的score(x)等于相邻数字差的平方和,比如score(125)=(1-2)*(1-2)+(2-5)*(2-5)=10。现在给出n和m,求满足条件的所有n进制的数字中有多少数字的score为m。(1<=m<=10^9)
思路:首先我们使用简单的DP,设f[i][j]表示和为i以j结尾的数字个数。由于这个m很大,这样肯定是不行的。我们发现,这个DP转移的时候每次都是一样的,这正是可以运用矩阵的地方。我们将条件(1)中不能以0开头改为不能以0结尾,这其实是等价的。以下以n=3为例。我们用(i,j)表示和为i以j结尾的方案数,使用矩阵递推时,设矩阵为a,用s[m]表示score为m的方案数,我们用[s[1],s[2],s[3],s[4]]*a=[s[2],s[3],s[4],s[5]],因为要加上以j结尾的状态,我们用s[i,j]表示以j结尾score为i为方案数,简写为(i,j)。那么我们给出完整的递推:
我们说明一下,比如第一行向第二行递推的时候,(1,1)可以向(2,2)递推的为什么我们不连呢?因为我们在第一行计算(2,2)时,就已经计算了从(1,1)转移过来的情况了。所以第一行除了向(5,0)(5,1)(5,2)连边外,其他的直接连下来。现在,有木有发现第一行有三个状态自始至终都没有用到,(1,1)(2,1)(3,1),为什么?其实我们以后能够到的只是可以递推到大于等于5的,而最有可能的(3,1)也只能递推到4,即后面加一个0或者2,所以我们可以将这些冗余状态删除。完了,就成这样了:
这样当n=6时,也只有100个状态,而不是开始的6*5*5=150个状态。比如计算n=6,m=1000,只有计算出a=a^(m-25)(a为转移矩阵),然后用S[i,j]这个数组,就是从S[1,0]到S[4,2]共9个元素,分别乘以a的最后(n-1)列?为什么不是n列呢?因为我们上面说转换为以0结尾,所以最后不能以0结尾。
#include <iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <map>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define abs(x) ((x)>=0?(x):-(x))
#define i64 long long
#define u32 unsigned int
#define u64 unsigned long long
#define clr(x,y) memset(x,y,sizeof(x))
#define CLR(x) x.clear()
#define ph(x) push(x)
#define pb(x) push_back(x)
#define Len(x) x.length()
#define SZ(x) x.size()
#define PI acos(-1.0)
#define sqr(x) ((x)*(x))
#define MP(x,y) make_pair(x,y)
#define FOR0(i,x) for(i=0;i<x;i++)
#define FOR1(i,x) for(i=1;i<=x;i++)
#define FOR(i,a,b) for(i=a;i<=b;i++)
#define rush() int CC;for(scanf("%d",&CC);CC--;)
#define Rush(n) while(scanf("%d",&n)!=-1)
using namespace std;
void RD(int &x){scanf("%d",&x);}
void RD(i64 &x){scanf("%I64d",&x);}
void RD(u32 &x){scanf("%u",&x);}
void RD(double &x){scanf("%lf",&x);}
void RD(int &x,int &y){scanf("%d%d",&x,&y);}
void RD(i64 &x,i64 &y){scanf("%I64d%I64d",&x,&y);}
void RD(u32 &x,u32 &y){scanf("%u%u",&x,&y);}
void RD(double &x,double &y){scanf("%lf%lf",&x,&y);}
void RD(int &x,int &y,int &z){scanf("%d%d%d",&x,&y,&z);}
void RD(i64 &x,i64 &y,i64 &z){scanf("%I64d%I64d%I64d",&x,&y,&z);}
void RD(u32 &x,u32 &y,u32 &z){scanf("%u%u%u",&x,&y,&z);}
void RD(double &x,double &y,double &z){scanf("%lf%lf%lf",&x,&y,&z);}
void RD(char &x){x=getchar();}
void RD(char *s){scanf("%s",s);}
void RD(string &s){cin>>s;}
void PR(int x) {printf("%d\n",x);}
void PR(int x,int y) {printf("%d %d\n",x,y);}
void PR(i64 x) {printf("%I64d\n",x);}
void PR(u32 x) {printf("%u\n",x);}
void PR(double x) {printf("%.3lf\n",x);}
void PR(char x) {printf("%c\n",x);}
void PR(char *x) {printf("%s\n",x);}
void PR(string x) {cout<<x<<endl;}
const i64 inf=((i64)1)<<60;
const double dinf=1e50;
const int INF=1000000000;
const int N=1005;
int M;
class Matrix
{
public:
u32 a[160][160];
void init(int x)
{
int i,j;
FOR0(i,M) FOR0(j,M) a[i][j]=0;
if(x==1)
{
FOR0(i,M) a[i][i]=1;
}
}
Matrix operator*(Matrix p)
{
Matrix ans;
ans.init(0);
int i,j,k;
FOR0(k,M) FOR0(i,M) FOR0(j,M)
{
ans.a[i][j]+=a[i][k]*p.a[k][j];
}
return ans;
}
Matrix Pow(int n)
{
Matrix ans,p=*this;
ans.init(1);
while(n)
{
if(n&1) ans=ans*p;
p=p*p;
n>>=1;
}
return ans;
}
void print()
{
puts("");
int i,j;
FOR0(i,M)
{
FOR0(j,M) printf("%u ",a[i][j]);
puts("");
}
puts("");
}
};
Matrix a;
int n,m;
int f[26][6],b[26][6],c[120];
int DFS(int sum,int pre)
{
if(sum==0) return 1;
if(sum<0) return 0;
if(f[sum][pre]!=-1) return f[sum][pre];
int ans=0,i;
FOR0(i,n) if(i!=pre) ans+=DFS(sum-sqr(i-pre),i);
return f[sum][pre]=ans;
}
int OK(int i,int j)
{
int k;
FOR0(k,n) if(k!=j&&i+sqr(j-k)>=(n-1)*(n-1)+1) return 1;
return 0;
}
void initMatrix()
{
clr(f,-1); clr(b,0);
int i,j,k,X=(n-1)*(n-1);
M=0;
FOR1(i,X) FOR0(j,n) if(OK(i,j))
{
c[M]=DFS(i,j);
b[i][j]=M++;
}
a.init(0);
int x,y;
FOR0(i,n) FOR0(j,n) if(i!=j)
{
x=b[X+1-sqr(i-j)][j];
y=b[X][i];
a.a[x][y]++;
}
for(i=2;i<=X;i++) FOR0(j,n) if(OK(i-1,j))
{
x=b[i][j];
y=b[i-1][j];
a.a[x][y]++;
}
}
int main()
{
int num=0;
rush()
{
RD(n,m);
printf("Case %d: ",++num);
if(n==2)
{
puts("1");
continue;
}
initMatrix();
u32 ans=0;
int i,j;
if(m<=(n-1)*(n-1))
{
FOR1(i,n-1) ans+=DFS(m,i);
PR(ans);
continue;
}
a=a.Pow(m-(n-1)*(n-1));
FOR0(i,M) for(j=M-n+1;j<M;j++) ans+=c[i]*a.a[i][j];
PR(ans);
}
}
lightOJ 1172 Krypton Number System(矩阵+DP)的更多相关文章
- UVa 11651 Krypton Number System DP + 矩阵快速幂
题意: 有一个\(base(2 \leq base \leq 6)\)进制系统,这里面的数都是整数,不含前导0,相邻两个数字不相同. 而且每个数字有一个得分\(score(1 \leq score \ ...
- Poj 2411 Mondriaan's Dream(压缩矩阵DP)
一.Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, ...
- hdu4975 网络流解方程组(网络流+dfs判环或矩阵DP)
http://acm.hdu.edu.cn/showproblem.php?pid=4975 A simple Gaussian elimination problem. Time Limit: 20 ...
- Find n‘th number in a number system with only 3 and 4
这是在看geeksforgeeks时看到的一道题,挺不错的,题目是 Given a number system with only 3 and 4. Find the nth number in th ...
- Moduli number system
A number system with moduli is defined by a vector of k moduli, [m1,m2, ···,mk]. The moduli must be p ...
- F - The Fun Number System(第二季水)
Description In a k bit 2's complement number, where the bits are indexed from 0 to k-1, the weight o ...
- hdu 4975 最大流问题解决队伍和矩阵,利用矩阵dp优化
//刚開始乱搞. //网络流求解,假设最大流=全部元素的和则有解:利用残留网络推断是否唯一, //方法有两种,第一种是深搜看看是否存在正边权的环.见上一篇4888 //至少四个点构成的环,另外一种是用 ...
- The Stern-Brocot Number System(排序二进制)
The Stern-Brocot Number System Input: standard input Output: standard output The Stern-Brocot tree i ...
- POJ 1023 The Fun Number System
Description In a k bit 2's complement number, where the bits are indexed from 0 to k-1, the weight o ...
随机推荐
- linux设备驱动模型
尽管LDD3中说对多数程序员掌握设备驱动模型不是必要的,但对于嵌入式Linux的底层程序员而言,对设备驱动模型的学习非常重要. Linux设备模型的目的:为内核建立一个统一的设备模型,从而又一个对系统 ...
- 什么是 block
什么是 block 1.提前准备好的一段可以执行的代码 2.block 可以当做参数传递 3.在需要的时候执行 block 4,block 中使用 self 时肯产生循环引用 block 做网络异步耗 ...
- CentOS-6.5安装配置JDK-7和JDK-8
安装说明 系统环境:centos-6.5 软件:jdk-7-linux-x64.rpm , jdk-8u5-linux-i586.tar.gz 下载地址:http://www.oracle.com/ ...
- Careercup - Google面试题 - 4807591515389952
2014-05-06 00:45 题目链接 原题: What would happen if you have only one server for a web cache (a web brows ...
- 输入adb shell 时 提示error: more than one device and emulator
第一种情况:确实用多个设备或者模拟器 解决办法:(指定连接某一个设备或者模拟器) 1.获取模拟器/设备列表 adb devices 2.指定device来执行adb shell adb -s ...
- windows server 2008 下安装openmeetings 2.2.0
经过两天的痛苦经历,终于完成了openmeetings的安装部署.其实步骤都很简单,只是网上的资料都是英文的,而且很多教程都是针对openmeeting之前的版本,导致我在部署的时候走了很多弯路.网上 ...
- IIS Express start introduction and applicationHost modification
1. First you need create a web project in VS 2. When you finish your project, click start then IIS E ...
- 2875: [Noi2012]随机数生成器 - BZOJ
DescriptionInput 包含6个用空格分割的m,a,c,X0,n和g,其中a,c,X0是非负整数,m,n,g是正整数. Output 输出一个数,即Xn mod gSample Input ...
- 关于iOS中的文本操作-管理text fields 和 text views
Managing Text Fields and Text Views 管理UITextField和UITextView实例 UITextField和UITextView的实例拥有两个最主要的功能:展 ...
- Codeforces 402A 402B 402C 402D
402A 直接暴力 #include <cstdio> #include <cstdlib> #include <cmath> #include <map&g ...