TC704div2 C ModEquationEasy 矩阵快速幂+dp

Problem Statement

    You are given the ints nK, and v



Consider the following modular equation with n variables: (x[0] * x[1] * x[2] * ... * x[n-1]) mod K = v. How many solutions does it have? 



Formally, we want to find the number of sequences (x[0], x[1], ..., x[n-1]) such that each x[i] is an integer between 0 and K-1, inclusive, and the product of all x[i] gives the remainder v when divided by K



Please compute and return the number of such sequences, modulo 10^9+7.

Definition

    
Class:ModEquationEasy
Method:count
Parameters:int, int, int
Returns:int
Method signature:int count(int n, int K, int v)
(be sure your method is public)

Limits

    
Time limit (s):2.000
Memory limit (MB):256
Stack limit (MB):256

Constraints

-n will be between 1 and 1,000,000,000, inclusive.
-K will be between 2 and 100, inclusive.
-v will be between 0 and (K-1), inclusive.

Examples

0) 
    
2
4
1
Returns: 2
The input describes the modular equation (x[0] * x[1]) mod 4 = 1. 



There are two solutions: (1, 1) and (3, 3).
1) 
    
2
4
0
Returns: 8
This time we have 8 solutions: (0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (2, 0), (3, 0) and (2, 2).
2) 
    
2
4
2
Returns: 4
 
3) 
    
3
7
5
Returns: 36
 
4) 
    
10
100
50
Returns: 683036071
 
5) 
    
1
2
0
Returns: 1
 

 

题意:

给你n,v,k,找出n个数,使得 (x[0] * x[1] * x[2] * ... * x[n-1]) mod K = v,其中x[i]在0~k之间

思路:

mat[i][j]:=最后一个数取成i,余数为j的个数

转移: mat[i][j] = mat[i][j]+mat[i][k]*mat[k][j];

用K*K的矩阵表示,每乘一次代表取了下一个数。

最后的答案是 mat[i][v] {0<=i<=k}

 

代码:

 

 1 int N,K,V;
 2 struct node{
 3     ll m[105][105];
 4     void clear(){
 5         mem(m);
 6     }
 7 }a;
 8 
 9 node mul(node a,node b){
10     node re; re.clear();
11     for(int i=0; i<K; i++)
12         for(int k=0; k<K; k++){
13             if(a.m[i][k]){
14                 for(int j=0; j<K; j++)
15                     re.m[i][j] = (re.m[i][j]+(a.m[i][k]*b.m[k][j])%mod)%mod;
16             }
17         }
18     return re;
19 }
20 
21 node qpow(int k){
22     node re; re.clear();
23     for(int i=0; i<=K; i++) re.m[i][i]=1;
24     while(k){
25         if(k&1) re = mul(re,a);
26         a = mul(a,a);
27         k >>= 1;
28     }
29     return re;
30 }
31 
32 int count(int n, int k, int v)  
33 {
34     N=n,K=k,V=v;
35     a.clear();
36      for(int i=0; i<K; i++){
37          for(int j=0; j<K; j++)
38              a.m[i][i*j%K]++;
39      }   
40      a = qpow(n-1);
41      ll ans = 0;
42      for(int i=0; i<K; i++){
43          ans = (ans+a.m[i][v])%mod;
44      }
45      return ans;
46 }  

 

转载于:https://www.cnblogs.com/yxg123123/p/6837711.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值