zoukankan      html  css  js  c++  java
  • loj Snakes 的 Naïve Graph 【数论】

    题目链接

    loj

    题解

    感谢珂神的指导orz

    观察式子(i imes j equiv 1 pmod m),显然(i,j)是模(m)意义下成对的逆元,只需统计模(m)意义下存在逆元的数的个数,即与(m)互质的数的个数(varphi(m))
    每对逆元的连边有两种情况,记逆元对数为(x),则方案数为(2^x)

    真的完了吗?难点才刚开始
    (m)意义下有的数逆元为本身!此时不能计入答案
    所以我们还需求模(m)意义下逆元为本身的数的个数

    重新理解一下中国剩余定理,本质是环同构
    (m = a_1a_2a_3dots)
    其中(a_i = p_i^{k_i})
    那么首先在模(a_i)意义下分别有一个整环
    我们把这些整环放在一起,用向量表示,成一个新环,可与模(m)意义下的整环一一对应,即环同构
    例如(Z/6 = Z/2 centerdot Z/3)
    则对应关系
    0 (0,0)
    1 (1,1)
    2 (0,2)
    3 (1,0)
    4 (0,1)
    5 (1,2)

    环同样满足加减乘
    所以我们需要求出在模每个(a_i)下平方等于(1)的数的个数,乘起来即可

    [egin{aligned} x^2 equiv 1 pmod m \ (x + 1)(x - 1) equiv 0 pmod m end{aligned} ]

    所以我们只需((x + 1)(x - 1))(m)的倍数即可
    对于(p > 2)(p)不能同时整除((x + 1))((x - 1)),所以只能一者为(0),所以有两种方案
    对于(p = 2)((x + 1)(x - 1))必须都是偶数,显然有一个不能整除(4),所以另一个应能整除(2^{k-1}),或者两个如(p > 2)的情况,有一者为(0),但是(k le 2)时会重复,所以特判一下,(k = 1)(1)(k = 2)(2),否则为(4)
    以上线筛处理即可

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define mp(a,b) make_pair<int,int>(a,b)
    #define cls(s) memset(s,0,sizeof(s))
    #define cp pair<int,int>
    #define LL long long int
    #define res register
    using namespace std;
    const int maxn = 10000005,maxm = 100005,INF = 1000000000,P = 311021;
    inline int read(){
    	int out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    	return out * flag;
    }
    int p[maxn],pi,isn[maxn],phi[maxn],N = 10000000;
    int f[maxn],bin[maxn],tw[maxn],tot[maxn],all[maxn];
    void init(){
    	phi[1] = 1;
    	for (res int i = 2; i <= N; i++){
    		if (!isn[i]){
    			p[++pi] = i,phi[i] = i - 1;
    			if (i == 2) tw[i] = 1;
    			else tot[i] = 1;
    		}
    		for (res int j = 1; j <= pi && i * p[j] <= N; j++){
    			isn[i * p[j]] = true;
    			if (i % p[j] == 0){
    				phi[i * p[j]] = phi[i] * p[j];
    				if (p[j] == 2){
    					tw[i * p[j]] = tw[i] + 1;
    					tot[i * p[j]] = tot[i];
    				}
    				else{
    					tw[i * p[j]] = tw[i];
    					tot[i * p[j]] = tot[i];
    				}
    				break;
    			}
    			phi[i * p[j]] = phi[i] * (p[j] - 1);
    			if (p[j] == 2){
    				tot[i * p[j]] = tot[i];
    				tw[i * p[j]] = tw[i] + 1;
    			}
    			else{
    				tot[i * p[j]] = tot[i] + 1;
    				tw[i * p[j]] = tw[i];
    			}
    		}
    	}
    	bin[0] = 1;
    	for (res int i = 1; i <= N; i++)
    		bin[i] = (bin[i - 1] << 1),bin[i] >= P ? (bin[i] -= P) : 0;
    	for (res int i = 1; i <= N; i++){
    		all[i] = bin[tot[i]];
    		if (tw[i] == 2) all[i] = all[i] * 2 % P;
    		else if (tw[i] > 2) all[i] = all[i] * 4 % P;
    	}
    	for (res int i = 1; i <= N; i++){
    		f[i] = f[i - 1] + bin[(phi[i] - all[i]) >> 1],f[i] >= P ? (f[i] -= P) : 0;
    	}
    }
    int c[maxn],ci;
    int main(){
    	init();
    	int q = read(),l,r;
    	while (q--){
    		l = read(); r = read();
    		printf("%d
    ",(f[r] - f[l - 1] + P) % P);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    sql server 查询数据判断为空
    sql 排序
    ASP.NE 上传文件控件
    JQ 获取下一个元素和获取下一个元素的[指定]子元素
    sql server 查询时间 格式化输出
    ASP.NET 页面验证cookie
    ASP.NET MD5加密
    HTML编辑器ASP.NET
    Repeater控件
    20150215-情愿
  • 原文地址:https://www.cnblogs.com/Mychael/p/9222551.html
Copyright © 2011-2022 走看看