传送门: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. Collections在sort()简单分析法源

    Collections的sort方法代码: public static <T> void sort(List<T> list, Comparator<? super T& ...

  2. Linux - 输入输出流程序 代码(C)

    输入输出流程序 代码(C) 本文地址:http://blog.csdn.net/caroline_wendy 使用输入输出流,控制文件流. STDIN_FILENO,STDOUT_FILENO代表标准 ...

  3. Windows 7 taskbar and startmenu pin

    原文 Windows 7 taskbar and startmenu pin 在Windows 7上,用户可以将自己喜欢的软件“钉”在开始菜单或任务栏,使用起来更加方便.但有时候我们也需要用程序来将这 ...

  4. UVA 10739 String to Palindrome(dp)

    Problem H String to Palindrome Input: Standard Input Output: Standard Output Time Limit: 1 Second In ...

  5. poj3278Catch That Cow(BFS)

    Catch That Cow Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 37094   Accepted: 11466 ...

  6. C#拖曳控件加载,bll报错问题

    C#拖曳控件加载,bll报错问题,加载时实例如化bll时加上一个判断 if (!(GetService(typeof(IDesignerHost)) != null            || Sys ...

  7. 开源数据库连接池之Tomcat内置连接池

    本篇介绍几种开源数据库连接池,同时重点讲述如何使用Tomcat服务器内置的数据库连接池. 之前的博客已经重点讲述了使用数据库连接池的好处,即是将多次创建连接转变为一次创建而使用长连接模式.这样能减少数 ...

  8. asp.net下用js实现弹出子窗口选定值并返回

    对应上一篇博客代码: 父页面: <head runat="server"> <meta http-equiv="X-UA-Compatible" ...

  9. windows lwp 乱码问题

    use LWP::UserAgent; use Encode; my $ua = LWP::UserAgent->new; $phone=$ARGV[0]; $cc=$ARGV[1]; $ua- ...

  10. 基于visual Studio2013解决面试题之0504单链表逆序

     题目