zoukankan      html  css  js  c++  java
  • [题解] Tenka1 Programmer Contest 2019 E

    https://tenka1-2019.contest.atcoder.jp/tasks/tenka1_2019_e

    首先所有系数(gcd)的质因子一定是满足条件的。

    (p mid f(x))就相当于(f(x) equiv 0 pmod p)

    然后显然(f(x) equiv f(xmod p) pmod p)

    那么(f(x))(p)不管(x)取值如何都为(0)当且仅当(f(0),f(1),cdots f(p-1) equiv 0 pmod p)

    (f(x))(mod p)下有因式(prod_{i=0}^{p-1} (x-i))。显然(prod_{i=0}^{p-1}(x-i) equiv 0 pmod p)

    这样我们就可以考虑枚举(n)以内的质数(p),然后check,但上面那个式子并不方便,我们想找到一个更简单且与其等价的因式。

    与其等价的因式应该是一个(p)次多项式

    又因为(p)是素数,对与(p)互质的数(x)都有(x^{p-1} equiv 1 pmod p),那么(x^{p-1}-1 equiv 0 pmod p),所以(x^p-x equiv 0 pmod p)。我们就找到了一个((x,p)=1)时与上面那个柿子等价的东西。

    如果((x,p) ot= 1)(p)是质数,那么显然有(p mid x),这种情况(x^p-x)还是满足要求的。

    所以(p mid f(x))(不论(x)的取值),当且仅当(f(x))有因式(x^p-x)

    于是枚举(n)以内的质数(p),将系数对(p)取模,然后暴力做除法即可。

    #include <bits/stdc++.h>
    using namespace std;
    #define rep(i,a,n) for (int i=a;i<n;i++)
    #define per(i,a,n) for (int i=n-1;i>=a;i--)
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define all(x) (x).begin(),(x).end()
    #define SZ(x) ((int)(x).size())
    typedef double db;
    typedef long long ll;
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    
    const int N=5e4+10;
    
    int gcd(int x,int y) {return y?gcd(y,x%y):x;}
    
    int vis[N],ps[N],tn;
    void sieve(int n) {
    	rep(i,2,n+1) {
    		if (!vis[i]) ps[tn++]=i;
    		for (int j=0;j<tn&&i*ps[j]<=n;j++) {
    			vis[i*ps[j]]=1;
    			if (i%ps[j]==0) break;
    		}
    	}
    }
    
    int a[N],n;
    
    bool check(int p) {
    	if (a[0]%p) return false;
    	static int f[N];
    	rep(i,0,n+1) f[i]=(a[i]%p+p)%p;
    	per(i,0,n-p+1) {
    		int j=i+p;
    		f[i+1]=(f[i+1]+f[j])%p;
    		f[j]=0;
    	}
    	rep(i,0,n+1) if (f[i]) return false;
    	return true;
    }
    
    set<int> ans;
    
    int main() {
    #ifdef LOCAL
    	freopen("a.in","r",stdin);
    #endif
    	scanf("%d",&n),sieve(n);
    	int g=0;
    	per(i,0,n+1) scanf("%d",&a[i]),g=gcd(g,abs(a[i]));
    	for (int i=2;i*i<=g;i++) {
    		if (g%i==0) {
    			ans.insert(i);
    			while (g%i==0) g/=i;
    		}
    	}
    	if (g!=1) ans.insert(g);
    	rep(i,0,tn) if (check(ps[i])) ans.insert(ps[i]);
    	for (auto p:ans) printf("%d
    ",p);
    	return 0;
    }
    
  • 相关阅读:
    关于使用CodeFirst,修改类或上下文时操作数据库报错解决方法
    解决:启用多线程调用webBrowsers函数报错:指定的转换无效
    强制IE浏览器或WebBrowser控件使用指定版本显示网页
    EF:分页查询 + 条件查询 + 排序
    (.NET高级课程笔记)委托、事件总结
    windows server 2008 磁盘挂载
    Git的使用
    VLAN原理详解
    Jumpserver的部署和使用
    进程与线程的理解
  • 原文地址:https://www.cnblogs.com/wxq1229/p/12556840.html
Copyright © 2011-2022 走看看