链接:https://ac.nowcoder.com/acm/contest/338/L
来源:牛客网
Consider digits strings with length n, how many different strings have the sum of digits are multiple of 4?
输入描述:
There are several test cases end with EOF. For each test case, there is an integer in one line: n, the length of the digits string. (1≤n≤1,000,000,000).
输出描述:
For each case, output the number of digits strings with length n have the sum of digits are multiple of 4 in one line. The numbers maybe very large, you should output the result modular 2019.
示例1
输出
复制3 25 249 479
题目大意 • 求长度为n的数字串中,有多少个这样数字串,其数字 之和是4的倍数(包括0) • 输入:每组测试数据一行,包含一个正整数n(1 ≤ c≤ 109) • 输出:对于每组测试数据,输出一行,包含一个整数, 表示有多少个这样数字串,其数字之和是4的倍数(包 括0)。因为这个结果很大,所以将值模2019输出 • 本题快速幂,复杂度为O(logn)。标程在1000组测试 数据下的运行时间约为60毫秒(第二标程运行时间约 30毫秒)。建议时间限制为1秒,空间限制为64M。

#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <cfloat> #include <climits> #include <iostream> #include <string> #include <vector> #include <list> #include <queue> #include <stack> #include <map> #include <set> #include <algorithm> #include <bitset> using namespace std; #define LL long long const int matrix_size = 4; const int MOD = 2019; int add(int a, int b) { a += b; if(a >= MOD) { return a - MOD; } return a; } struct Matrix { int size; int num[matrix_size][matrix_size]; void operator=(const Matrix &m) { for(int i = 0; i < size; ++i) { memcpy(num[i], m.num[i], sizeof(int) * size); } } void Init() { for(int i = 0; i < size; ++i) { memset(num[i], 0, sizeof(int) * size); num[i][i] = 1; } } void Set() { size = 4; memset(num, 0, sizeof(num)); for(int j = 0; j < 4; ++j) { for(int i = 0; i < 10; ++i) { ++num[(j + i) % 4][j]; } } } void operator*=(const Matrix &m) { static Matrix ans; ans.size = size; for(int i = 0; i < size; ++i) { for(int j = 0; j < size; ++j) { ans.num[i][j] = 0; for(int k = 0; k < size; ++k) { ans.num[i][j] = add(ans.num[i][j], (LL)num[i][k] * m.num[k][j] % MOD); } } } (*this) = ans; } void fast_pow(LL n) { static Matrix ans; ans.size = size; for(ans.Init(); n != 0; n >>= 1) { if((n & 1) == 1) { ans *= (*this); } (*this) *= (*this); } (*this) = ans; } }; int n; Matrix m; int main() { #ifdef Dmaxiya freopen("test.txt", "r", stdin); #endif // Dmaxiya ios::sync_with_stdio(false); while(scanf("%d", &n) != EOF) { m.Set(); m.fast_pow(n); printf("%d ", m.num[0][0]); } return 0; }
标答

•#include <stdio.h> •#define M 2019 •#define L 4 •#define LP(i) for(i=0;i<L;++i) •void Product(int x[L][L],int y[L][L],int z[L][L]){ • int i,j,k,w[L][L]={0}; • LP(i)LP(j)LP(k)w[i][j]=(w[i][j]+x[i][k]*y[k][j])%M; • LP(i)LP(j)z[i][j]=w[i][j];} • •void FPow(int n,int r[L][L]){ • int i,j,A[L][L]={{3,2,2,3},{3,3,2,2},{2,3,3,2},{2,2,3,3}}; • LP(i)LP(j)r[i][j]=i==j?1:0; •while(n){ •if(n&1)Product(r,A,r); •Product(A,A,A); • n>>=1;}} •int cal(int n){ •int r[L][L]; •FPow(n,r); • return (3*r[0][0]+3*r[0][1]+2*r[0][2]+2*r[0][3])%M;} • •int main(){ •int n; •while(scanf("%d",&n)!=EOF&&n>0) •printf("%d ",cal(n-1)); •return 0;}
解题思路(续) • 矩阵 • 3 2 2 3 • 3 3 2 2 • 2 3 3 2 • 2 2 3 3 • 有四个特征根,分别是0,10,1+i,1-i; • 所以an=x10n+ycos(nπ/4)+zsin(nπ/4),根据 a1=3,a2=25,a3=249,可得: • an=(10n+2sqrt(2)ncos(nπ/4))/4; • 同样快速幂求得答案。

•#include <stdio.h> •#define M 2019 • int rt[2][32],et[8]={2,2,0,-4,-8,-8,0,16}; •int FPow(int f,int n){ • int r=1,m=0; •while(n){ • if(n&1)r=(r*rt[f][m])%M; • m++; • n>>=1;} •return r;} • •int cal(int n){ •int r1,r2; • r1=FPow(0,n); • r2=((FPow(1,n/8)*et[n%8])%M+M)%M; • return ((r1+r2)*505)%M; • } •int main(){ •int n,i; • rt[0][0]=10;rt[1][0]=16; • for(i=1;i<32;++i){ • rt[0][i]=(rt[0][i-1]*rt[0][i-1])%M; • rt[1][i]=(rt[1][i-1]*rt[1][i-1])%M;} •while(scanf("%d",&n)!=EOF&&n>0) •printf("%d ",cal(n)); •return 0;}
STZG的代码