K(K>=3)个猿辅导的老师们在玩一个击鼓传花的小游戏。每击一次鼓,拿着花的老师要将花交给别人,不能留在自己手中。游戏开始前花在小猿手中,求击了N次鼓后,这朵花又回到小猿手中的方案数,请输出这个数模1000000007后的结果。
输入两个数N,K。
20%的数据:(3<=K<=10, 1<= N<=10)
70%的数据:(3<=K<=1000, 1<= N<=1000)
100%的数据:(3<=K<=10^9, 1<= N<=10^9)
输出方案数模1000000007后的结果
3 3
2
#include<iostream> #include<vector> using namespace std; int main() { long long n, k; cin >> n >> k; if (k < 3)return 0; vector<vector<long long>>dp(n + 1, vector<long long>(k + 1)); dp[0][0] = 1; dp[0][1] = 0; for (long long i = 1; i <= n; i++) { dp[i][0] = dp[i - 1][1] % 1000000007; dp[i][1] = (dp[i - 1][0] * (k - 1)) % 1000000007 + (dp[i - 1][1] * (k - 2)) % 1000000007; } cout << dp[n][0] << endl; system("pause"); return 0; }
#include <bits/stdc++.h> #define int long long using namespace std; const int MODN=1000000007; vector<vector<int>> mul(vector<vector<int>> &a,vector<vector<int>> &b){ vector<vector<int>> ret(2,vector<int>(2,0)); for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++) ret[i][j]+=a[i][k]*b[k][j],ret[i][j]%=MODN; return ret; } vector<vector<int>> quick_pow(vector<vector<int>> & mat,int n){ vector<vector<int>> ret = {{1,0},{0,1}}; while(n){ if(n&1)ret=mul(ret,mat); mat=mul(mat,mat); n>>=1; } return ret; } int32_t main(){ int n,k;cin>>n>>k; if(n==1)cout<<0<<endl; else if(n==2)cout<<k-1<<endl; else{ vector<vector<int>> mat={{k-2,k-1},{1,0}}; mat=quick_pow(mat,n-2); int ret=0; vector<int> mv={k-1,0}; for(int i=0;i<2;i++)ret+=mat[0][i]*mv[i],ret%=MODN; cout<<ret<<endl; } return 0; }
import java.util.*; public class Main{ public static void main(String[] args){ Scanner input; int N, K; input = new Scanner(System.in); while(input.hasNext()){ N = input.nextInt(); K = input.nextInt(); System.out.println(new Main().Solution(N, K)); } } private long Solution(int N, int K){ int M; long[][] A, An; M = 1000000007; if(N == 1) return 0; if(N == 2) return K - 1; A = new long[][]{{K - 2, 1}, {K - 1, 0}}; An = pow(A, N - 2); return An[0][0] * (K - 1) % M; } private long[][] pow(long[][] A, int n){ Stack<Integer> stack; long[][] ans; stack = new Stack<>(); ans = new long[][]{{1, 0}, {0, 1}}; while(n > 0){ stack.push(n % 2); n /= 2; } while(!stack.isEmpty()){ multi(ans, ans); if(stack.pop() == 1) multi(ans, A); } return ans; } private void multi(long[][] A, long[][] B){ long a00, a01, a10, a11; int M; M = 1000000007; a00 = (A[0][0] * B[0][0] + A[0][1] * B[1][0]) % M; a01 = (A[0][0] * B[0][1] + A[0][1] * B[1][1]) % M; a10 = (A[1][0] * B[0][0] + A[1][1] * B[1][0]) % M; a11 = (A[1][0] * B[0][1] + A[1][1] * B[1][1]) % M; A[0][0] = a00; A[0][1] = a01; A[1][0] = a10; A[1][1] = a11; } }
坑点在取模,乘法套加法的别乱取模,如
通过画一棵树分析,如1的子节点可以有2,3,4...,找出规律,除了之外,另一部分为首项是,公差是的等比数列,根据的奇偶性来决定加上还是减去这一部分,于是式子可以化简为,又, 于是
#include <bits/stdc++.h> using namespace std; long long p = 1000000007; long long quick_pow(long long a, long long b) { long long ans = 1; while(b) { if(b & 1)ans = ans * a % p; a = a * a % p; b >>= 1; } return ans; } int main() { long long n, k; cin >> n >> k; if(n == 1) { cout << 0 << endl; return 0; } else if(n == 2) { cout << k - 1 << endl; return 0; } long long ans = 0; long long odd = n % 2 == 1 ? -1 : 1; //(-1)^n ans = ((k - 1) * (quick_pow(k - 1, n - 1) + odd)) % p;//(k-1)*[(k-1)^(n-1)+(-1)^n] ans = ans * quick_pow(k, p - 2); ans %= p; cout << ans << endl; return 0; }
import java.util.Scanner; import java.lang.Math; public class Main{ public static void main(String[] args) { int s=1000000007; Scanner sc=new Scanner(System.in); int k=sc.nextInt(); int n=sc.nextInt(); long[] f=new long[n+3]; f[2]=k-1;f[1]=0; long sum=(k-1); for(int i=3;i<=n;i++) { sum=sum*(k-1); //k=951 n=223 f[i]=(sum-f[i-1])%s; sum=sum%s; } System.out.print(f[n]>=0?f[n]:f[n]+s); } }
import java.util.Arrays; import java.util.Scanner; public class Main { public static final int mod=1000000007; public static void main(String[] args) { Scanner sin=new Scanner(System.in); while(sin.hasNext()){ int n=sin.nextInt(); int k=sin.nextInt(); System.out.println(calcu(n,k)); } } public static long calcu(int n,int k){ //求dp[n][0]的方案数 long[][] dp=new long[n][k]; Arrays.fill(dp[0],1L); dp[0][0]=0; for(int i=1;i<n;i++){ long sum=0; for(long num:dp[i-1]) sum+=num; for(int j=0;j<k;j++){ dp[i][j]=sum-dp[i-1][j]; while(dp[i][j]>mod){ dp[i][j]%=mod; } } } return dp[n-1][0]; } }70%通过率,100%的是数学家吧
def mul2Matrix(x,y): # 二维矩阵相乘的实现 ans = [[0 for i in range(2)]for j in range(2)] for i in range(2): for j in range(2): for k in range(2): ans[i][j] += (x[i][k]% 1000000007) * (y[k][j] % 1000000007) return ans def mul1Matrix(x,y): # 二维矩阵与size为(2*1)的矩阵相乘 ans = [[0] for j in range(2)] for i in range(2): for k in range(2): ans[i][0] += (x[i][k]% 1000000007) * (y[k][0]% 1000000007) return ans def quickMatrix(m,n): # 矩阵快速幂运算实现 E = [[0 for i in range(2)]for j in range(2)] for i in range(2): E[i][i] = 1 while(n): if n % 2 != 0: E = mul2Matrix(E,m) m = mul2Matrix(m,m) n >>= 1 return E if __name__ == '__main__': n, k = map(int, input().split()) m = [[k-2,k-1],[1,0]] x = [[k-1],[0]] # 注意考虑特殊情况,若不加此条件,只能通过90%的case if n >= 2: tmp = quickMatrix(m, n-2) print(mul1Matrix(tmp,x)[0][0]%1000000007) else: print(0)
n, k = map(int, input().split()) lis = [0] for i in range(1,n): lis.append((k-1)**i-lis[i-1]) print(lis[-1]%1000000007)