Tenka1 Programmer Contest 2019

A.一定是前半段白后半段黑,枚举分界点预处理前后缀和。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<iostream>
 5 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 6 typedef long long ll;
 7 using namespace std;
 8 
 9 const int N=200010;
10 char s[N];
11 int n,ans,pre[N],suf[N];
12 
13 int main(){
14     freopen("a.in","r",stdin);
15     freopen("a.out","w",stdout);
16     scanf("%d%s",&n,s+1); ans=n+1;
17     rep(i,1,n) pre[i]=pre[i-1]+(s[i]=='#');
18     for (int i=n; i; i--) suf[i]=suf[i+1]+(s[i]=='.');
19     rep(i,0,n) ans=min(ans,pre[i]+suf[i+1]);
20     printf("%d\n",ans);
21     return 0;
22 }
A

B.总数-存在某个集合超过总和一半的方案数,先默认这个大集合是R最后再乘3。

f[i][j]表示前i个数中R中数之和为j,不在R中的数随意放入G和B的方案数。发现这样可能会多考虑空集,于是再令g[i][j]表示前i个数中R中数和为j,不在R中的数全部放入G的方案数,做个类似的DP即可。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<iostream>
 5 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 6 typedef long long ll;
 7 using namespace std;
 8 
 9 const int N=310,mod=998244353;
10 int n,ans,sm,a[N],f[N*N],g[N*N];
11 
12 int ksm(int a,int b){
13     int res=1;
14     for (; b; a=1ll*a*a%mod,b>>=1)
15         if (b & 1) res=1ll*res*a%mod;
16     return res;
17 }
18 
19 int main(){
20     freopen("b.in","r",stdin);
21     freopen("b.out","w",stdout);
22     scanf("%d",&n); ans=(ksm(3,n)-3ll*ksm(2,n)+3+3ll*mod)%mod;
23     rep(i,1,n) scanf("%d",&a[i]),sm+=a[i];
24     f[0]=g[0]=1;
25     rep(i,1,n) for (int j=sm; ~j; j--){
26         f[j]=(f[j]*2ll+(j>=a[i]?f[j-a[i]]:0))%mod;
27         g[j]=(g[j]+(j>=a[i]?g[j-a[i]]:0))%mod;
28     }
29     rep(i,(sm+1)/2,sm-1) ans=(ans-3ll*(f[i]-2ll*g[i])+3ll*mod)%mod;
30     printf("%d\n",ans);
31     return 0;
32 }
B

C.结论:p能成为答案,当且仅当:p是所有系数gcd的质因子,或(x^p-x)能整除原多项式。

第一种情况由裴蜀定理知显然。第二种情况我是这样理解的:若两个多项式次数相同且所有根都相同,那么它们就是同一个多项式,在模意义下或许同样如此。那么由于1~p-1全部为原多项式的根,也就是x(x-1)(x-2)...(x-p+1)能整除原式。而这个式子和(x^p-x)在模p意义下是相等的,于是直接判断(x^p-x)能否整除原式即可。

下面考虑如何判断(x^n-1)是否整除一个多项式,发现只要判断“所有%n同余的次数项的系数之和是否全为0”即可。总复杂度O(n^2)。

 1 #include<set>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 5 typedef long long ll;
 6 using namespace std;
 7 
 8 const int N=200010;
 9 int n,m,a[N],h[N];
10 set<int>ans;
11 
12 void chk(int p){
13     rep(i,0,p-2) h[i]=0;
14     rep(i,0,n) h[i%(p-1)]=(h[i%(p-1)]+a[i])%p;
15     rep(i,0,p-2) if (h[i]) return;
16     ans.insert(p);
17 }
18 
19 int main(){
20     freopen("c.in","r",stdin);
21     freopen("c.out","w",stdout);
22     scanf("%d",&n);
23     for (int i=n; ~i; i--) scanf("%d",&a[i]),m=__gcd(m,abs(a[i]));
24     for (int i=2; i*i<=m; i++) if (m%i==0){
25         ans.insert(i);
26         while (m%i==0) m/=i;
27     }
28     if (m!=1) ans.insert(m);
29     rep(i,2,n) if (a[0]%i==0){
30         bool flag=1;
31         for (int j=2; j*j<=i; j++) if (i%j==0){ flag=0; break; }
32         if (flag) chk(i);
33     }
34     for (set<int>::iterator it=ans.begin(); it!=ans.end(); it++) printf("%d\n",*it);
35     return 0;
36 }
C

 

posted @ 2019-04-22 20:38  HocRiser  阅读(161)  评论(0编辑  收藏  举报