解题报告:HDU_6176 Function Counting (离散化DP+矩阵快速幂)

题目链接

题意:求满足题目的三个要求的置换的方案

思路:

分析题意发现是一个多重背包

设每个物品的代价为x,价值为y

则物品的代价为满足(2*t+1)*x==k , t 为自然数

对应的价值为2^x

代价为1和2的物品的价值比较特殊,为2^(x-1)

另外代价为2的物品会带上一个(4,4)的物品(交叉取置换)

于是就可以得到一个线性递推方程,基于n和k的范围采用不同的方法计算结果

矩阵快速幂的复杂度为

离散化DP的复杂度为 (d(k)为k的因子个数)

以上复杂度都为估计的上界,实际复杂度很难达到

那么选k=100作为分界,使得复杂度约在1e7的级别


代码:

#include

#define pii pair
#define fi first
#define se second
const int mod = 1e9+7 , N = 105;
using namespace std;

long long qpow(long long x,long long y){
   long long res = 1;
   while(y){
      if(y&1) res = res * x % mod;
      y>>=1; x = x * x % mod;
   }return res;
}

inline int oper(int x){return qpow(2,x-(x<=2));}

vectortim;
map< int ,int > dp;
int n,m,Dp[N];



namespace fast_Matrix{

int nn ;
const int MAX_E = N;
long long tmp[MAX_E][MAX_E];
long long mat[MAX_E][MAX_E];
long long res[MAX_E][MAX_E];
inline void mut(long long a[MAX_E][MAX_E],long long b[MAX_E][MAX_E]){
   memset(tmp,0,sizeof(tmp));
   for(int i=0;i=mod)mat[0][tim[i].fi-1]-=mod;
}
for(int i=0;i>=1;
    }
    long long val = 0;
    for(int i=0,j=m;i<=m;++i,--j)val = (val+1LL*Dp[j]*res[0][i])%mod;
    return val;
}

}
using namespace fast_Matrix;

long long work1(){
   memset(Dp,0,sizeof(Dp));Dp[0]=1;
   for(int i=0;i<=m;++i)if(Dp[i])
      for(int j=0;j'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}

int main()
{
   int T = read();
   while(T--){tim.clear();
      n = read(); m = read();
      int ed = sqrt(m+0.5);
      bool _2 = false;
      for(int i=1;i<=ed;++i){
         if(m%i==0){
            int t = m/i;
            if(i&1){
               if(t==2)_2=true,tim.emplace_back(4,4);
               tim.emplace_back(t,oper(t));
            }
            if((t&1)&&t!=i){
               if(i==2)_2=true,tim.emplace_back(4,4);
               tim.emplace_back(i,oper(i));
            }
         }
      }sort(tim.begin(),tim.end());
      if(_2&&m<4)m=4;
      printf("%lld\n",m


你可能感兴趣的:(离散,动态规划,计数)