• [Sdoi2017]序列计数 [矩阵快速幂]


    [Sdoi2017]序列计数

    题意:长为(n le 10^9)由不超过(m le 2 cdot 10^7)的正整数构成的和为(tle 100)的倍数且至少有一个质数的序列个数


    总-没有质数

    裸矩阵快速幂,(i ightarrow (i+k)mod t)

    但是构造矩阵m个数一个个试的话复杂度(O(mt))

    我们只管心(mod t)之后的结果,处理处每个模t等价类的个数用它来构造矩阵就好了。我是zz

    注意卡内存,存质数的数组可以小一点

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #include <ctime>
    using namespace std;
    const int N=2e7+5, mo=20170408;
    typedef long long ll;
    inline int read() {
    	char c=getchar(); int x=0, f=1;
    	while(c<'0' || c>'9') {if(c=='-')f=-1; c=getchar();}
    	while(c>='0' && c<='9') {x=x*10+c-'0'; c=getchar();}
    	return x*f;
    }
    
    int n, m, t;
    int p[2000000], notp[N], c1[105], c2[105];
    void sieve(int n) {
    	notp[1]=1;
    	for(int i=2; i<=n; i++) { //printf("i %d
    ",i);
    		if(!notp[i]) p[++p[0]]=i;
    		for(int j=1; j<=p[0] && i*p[j]<=n; j++) { //printf("j %d
    ",p[j]);
    			notp[ i*p[j] ]=1;
    			if(i % p[j] == 0) break;
    		}
    	}
    	for(int i=1; i<=n; i++) c1[ i%t ]++, c2[ i%t ] += notp[i];
    }
    
    inline void mod(ll &x) {if(x>=mo) x-=mo;}
    
    struct meow {
    	ll a[101][101];
    	meow() {memset(a, 0, sizeof(a));}
    	ll* operator [](int x) {return a[x];}
    	void ini() {for(int i=0; i<t; i++) a[i][i]=1;}
    }g, a;
    
    meow operator *(meow a, meow b) {
    	meow c;
    	for(int i=0; i<t; i++)
    		for(int k=0; k<t; k++)
    			for(int j=0; j<t; j++)
    				mod(c[i][j] += a[i][k] * b[k][j] %mo);
    	return c;
    }
    meow operator ^(meow a, int b) {
    	meow ans; ans.ini();
    	for(; b; b>>=1, a=a*a)
    		if(b&1) ans=ans*a;
    	return ans;
    }
    
    void build1() {
    	for(int i=0; i<t; i++)
    		for(int j=0; j<t; j++) g[i][ (i + j)%t ] += c1[j];
    }
    void build2() { 
    	a = meow(); g = meow();
    	for(int i=0; i<t; i++)
    		for(int j=0; j<t; j++) g[i][ (i + j)%t ] += c2[j];
    }
    int main() {
    	freopen("count.in", "r", stdin);
    	freopen("count.out", "w", stdout);
    	n=read(); m=read(); t=read();
    	sieve(m);
    	
    	build1();
    	a[0][0]=1; a = (g^n) * a;
    	ll ans = a[0][0];  
    	
    	build2();
    	a[0][0]=1; a = (g^n) * a;
    	ans = (ans - a[0][0] + mo) % mo;
    	
    	cout << ans;
    }
    
    
  • 相关阅读:
    牛客小白月赛2 D 虚虚实实 【欧拉图】【连通图】
    牛客小白月赛2 A 数字方阵【随机】【找规律】
    牛客小白月赛1 J おみやげをまらいました 【MAP】
    牛客小白月赛1 I あなたの蛙が帰っています 【卡特兰数】
    欧拉函数
    乘法逆元
    扩展欧几里得
    快速乘法
    JPEG图像压缩出现资源不足问题的解决
    如何避免关键程序被意外关闭?
  • 原文地址:https://www.cnblogs.com/candy99/p/6699743.html
Copyright © 2020-2023  润新知