传送门:Gift

题意:由n(n<=1e9)个珍珠构成的项链,珍珠包含幸运数字(有且仅由4或7组成),取区间[L,R]内的数字,相邻的数字不能相同,且旋转得到的相同的数列为一种,为最终能构成多少种项链。

分析:这是我做过的最为综合的一道题目(太渣了),首先数位dp筛选出区间[L,R]内的幸运数字总数,dp[pos]表示非限制条件下还有pos位含有的幸运数字个数,然后记忆化搜索一下,随便乱搞的(直接dfs不知会不会超时,本人做法900+ms险过,应该直接dfs会超时),再不考虑旋转相同的情况,可以dp再构造矩阵,dp[i][0]表示到达第i位时,最后一个珠子与第一个珠子不同,dp[i][1]表示到达第i位最后一个珠子与第一个相同,则状态转移方程为:

dp[i][0]=dp[i-1][0]*(m-2)+dp[i-1][1]*(m-1)(m为幸运数字种类).

dp[i][1]=dp[i-1][0]*1

上面构造矩阵快速幂求出总数后再由Burnside定理+容斥得到答案,这个问题较为常见,可参考poj2888做法。

#include <stdio.h>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <cstdlib>
#define LL long long
#define N 25
#define mod 1000000007
using namespace std;
/**************************矩阵快速幂**************************/
struct matrix
{
LL m[][];
void init()
{
for(int i=;i<;i++)
for(int j=;j<;j++)
m[i][j]=(i==j);
}
}M;
matrix mult(matrix a,matrix b)
{
matrix c;
memset(c.m,,sizeof(c.m));
for(int k=;k<;k++)
for(int i=;i<;i++)
{
if(a.m[i][k]==)continue;
for(int j=;j<;j++)
{
c.m[i][j]=(c.m[i][j]+a.m[i][k]*b.m[k][j])%mod;
}
} return c;
}
matrix quick_pow(matrix a,int n)
{
matrix res;
res.init();
while(n)
{
if(n&)res=mult(res,a);
a=mult(a,a);
n>>=;
}
return res;
}
LL calc(LL n,LL m)
{
matrix res;
res.m[][]=m-;res.m[][]=m-;
res.m[][]=;res.m[][]=;
res=quick_pow(res,n-);
// printf("m=%lld n=%lld res=%lld\n",m,n,res.m[0][1]);
return m*res.m[][]%mod;
}
/**************************矩阵快速幂**************************/
LL POW(LL a,LL n)
{
LL res=;
a%=mod;
while(n)
{
if(n&)res=res*a%mod;
a=a*a%mod;
n>>=;
}
return res;
}
/**********************容斥**************************/
#define MAXN 12
#define MAXM 32000
#define EPS 1e-8
bool p[MAXM];
vector<int> prime;
vector<int> factor;
vector<int> primefactor;
void Init() {
int i, j;
prime.clear();
memset(p, true, sizeof(p));
for (i = ; i < ; i++) {
if (p[i]) {
for (j = i * i; j < MAXM; j += i)
p[j] = false;
}
}
for (i = ; i < MAXM; i++) {
if (p[i])
prime.push_back(i);
}
}
void Prime(int x) {
int i, tmp;
primefactor.clear();
tmp = (int) (sqrt((double) x) + EPS);
for (i = ; prime[i] <= tmp; i++) {
if (x % prime[i] == ) {
primefactor.push_back(prime[i]);
while (x % prime[i] == )
x /= prime[i];
}
}
if (x > )
primefactor.push_back(x);
}
int Mul(int x, int &k) {
int i, ans;
ans = ;
for (i = k = ; x; x >>= , i++) {
if (x & ) {
k++;
ans *= primefactor[i];
}
}
return ans;
}
LL Phi(int x) {
int i, j, t, ans, tmp;
Prime(x);
ans = ;
t = (int) primefactor.size();
for (i = ; i < ( << t); i++) {
tmp = Mul(i, j);
if (j & )
ans += x / tmp;
else
ans -= x / tmp;
}
return (x - ans) %mod;
}
/**********************容斥**************************/
LL solve(LL n,LL m)
{
LL ans=;
for(int i=;i*i<=n;i++)
{
if(n%i==)
{
int a=i,b=n/i;
if(i*i==n)
{
ans=(ans+Phi(n/a)*calc(a,m))%mod;
}
else
{
ans=(ans+Phi(n/a)*calc(a,m))%mod;
ans=(ans+Phi(n/b)*calc(b,m))%mod;
}
}
}
ans=ans*POW(n,mod-)%mod;
return ans;
}
/************************数位dp**********************/
LL dig[],dp[];
LL dfs(int pos,int flag,int limit,int fzore)
{
if(pos==)return flag;
if(!fzore&&!limit&&~dp[pos])return dp[pos];
int len=limit?dig[pos]:;
LL ans=;
for(int i=;i<=len;i++)
{
if(i==||i==||i==){
if(fzore&&i==)ans+=dfs(pos-,,i==len&&limit,);
else if(i==||i==)ans+=dfs(pos-,,i==len&&limit,);}
}
if(!fzore&&!limit)dp[pos]=ans;
return ans;
}
LL fun(LL x)
{
int len=;
if(x<)return ;
while(x)
{
dig[++len]=x%;
x/=;
}
return dfs(len,,,);
}
/************************数位dp**********************/
int main()
{
LL n,L,R;
Init();
memset(dp,-,sizeof(dp));
while(scanf("%lld%lld%lld",&n,&L,&R)>)
{
LL num=fun(R)-fun(L-);
if(n==)
{
puts("");continue;
}
if(n==)
{
printf("%d\n",num%mod);
continue;
}
printf("%d\n",solve(n,num)); }
}

HUST 1569(Burnside定理+容斥+数位dp+矩阵快速幂)的更多相关文章

  1. hdu5564--Clarke and digits(数位dp+矩阵快速幂)

    Clarke and digits 问题描述 克拉克是一名人格分裂患者.某一天,克拉克变成了一个研究人员,在研究数字. 他想知道在所有长度在[l,r]之间的能被7整除且相邻数位之和不为k的正整数有多少 ...

  2. BZOJ3329 Xorequ(数位dp+矩阵快速幂)

    显然当x中没有相邻的1时该式成立,看起来这也是必要的. 于是对于第一问,数位dp即可.第二问写出dp式子后发现就是斐波拉契数列,矩阵快速幂即可. #include<iostream> #i ...

  3. BZOJ 3329 Xorequ:数位dp + 矩阵快速幂

    传送门 题意 现有如下方程:$ x \oplus 3x = 2x $ 其中 $ \oplus $ 表示按位异或. 共 $ T $ 组数据,每组数据给定正整数 $ n $,任务如下: 求出小于等于 $ ...

  4. BZOJ3329: Xorequ(二进制数位dp 矩阵快速幂)

    题意 题目链接 Sol 挺套路的一道题 首先把式子移一下项 \(x \oplus 2x = 3x\) 有一件显然的事情:\(a \oplus b \leqslant c\) 又因为\(a \oplus ...

  5. 2018.09.27 hdu5564Clarke and digits(数位dp+矩阵快速幂)

    传送门 好题啊. 我只会写l,rl,rl,r都很小的情况(然而题上并没有这种数据范围). 但这个dp转移式子可以借鉴. 我们用f[i][j][k]f[i][j][k]f[i][j][k]表示当前在第i ...

  6. bnuoj 34985 Elegant String DP+矩阵快速幂

    题目链接:http://acm.bnu.edu.cn/bnuoj/problem_show.php?pid=34985 We define a kind of strings as elegant s ...

  7. HDU 5434 Peace small elephant 状压dp+矩阵快速幂

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant  Accepts: 38  Submissions: ...

  8. 【BZOJ】2004: [Hnoi2010]Bus 公交线路 状压DP+矩阵快速幂

    [题意]n个点等距排列在长度为n-1的直线上,初始点1~k都有一辆公车,每辆公车都需要一些停靠点,每个点至多只能被一辆公车停靠,且每辆公车相邻两个停靠点的距离至多为p,所有公车最后会停在n-k+1~n ...

  9. 【BZOJ】4861: [Beijing2017]魔法咒语 AC自动机+DP+矩阵快速幂

    [题意]给定n个原串和m个禁忌串,要求用原串集合能拼出的不含禁忌串且长度为L的串的数量.(60%)n,m<=50,L<=100.(40%)原串长度为1或2,L<=10^18. [算法 ...

随机推荐

  1. .NET支持上下左右移动操作

    效果如下图: 代码如下: public partial class ShowSet : System.Web.UI.Page { Hashtable resources = EquStatusSear ...

  2. OFBIZ分享:利用Nginx +Memcached架设高性能的服务

    近年来利用Nginx和Memcached来提高站点的服务性能的作法,如一夜春风般的遍及大江南北,越来越多的门户站点和电子商务平台都採用它们来为自己的用户提供更好的服务体验.如:网易.淘宝.京东.凡客等 ...

  3. CuSparse 第一章

    (部分翻译) 第一章 介绍 1. 命名惯例 CUSPARSE 包含了一系列处理稀疏矩阵的基本的线性代数子程式.是cuda函数库的一部分,从C,C++中调用. 该库例程可以分为四类: 第一层:在稠密向量 ...

  4. 泛虚拟化技术(以Xen为例)

    一.概述    最主要的特点是:修改Guest OS的内核代码.通过修改内核,使Guest OS明白自己是运行在R-1,不要直接去运行特权指令,如果要运行就去Hypercall(主动VMM陷入).   ...

  5. C++ 左值 右值

    最近在研究C++ 左值 右值,搬运.收集了一些别人的资料,供自己记录和学习,若以后看到了更好的解释,会继续补充.(打“?”是我自己不明白的地方 )   参考:<Boost程序库探秘——深度解析C ...

  6. Java:Java快速入门

    链接地址:http://www.cnblogs.com/happyframework/p/3332243.html 你好,世界! 源代码组织方式 Java程序由package+class组成,pack ...

  7. Amazon RDS的通用型存储(SSD)

    在今年的6月份,我们曾介绍过为Amazon EC2实例提供的基于SSD的弹性块级存储. 在公布几个月过后,这样的被称为通用型存储(SSD)的新型选择方式在创建新的EBS卷中已经占到了90%,我们从客户 ...

  8. SRM 583 Div II Level One:SwappingDigits

    题目来源:http://community.topcoder.com/stat?c=problem_statement&pm=12609 #include <iostream> # ...

  9. xcode6 中增加SDWebImage/SDWebImageDownloaderOperation.m报错解决方法

    报错报错:Use of undeclared identifier '_executing' / '_finished': 解决方法例如以下:

  10. ubuntu14操作系统chrome标签和书签乱码解决

    ubuntu操作系统更新后.发现chrome标签和书签中文都无法显示. 解决的方法: 打开配置文件 sudo vim /etc/fonts/conf.d/49-sansserif.conf <! ...