51nod 1135
题目描述
求小于1e9的素数p的原根
#include <bits/stdc++.h>
using namespace std;
int pi[40];
int tot=0;
int power(int x,int n,int p){
int base=x;
int ans=1;
while(n){
if(n&1){
ans=1ll*ans*base%p;
}
n>>=1;
base=1ll*base*base%p;
}
return ans;
}
int main(){
int p;
scanf("%d",&p);
int x=p-1;
for(int i=2;i*i<=x;i++){
if(x%i==0){
pi[++tot]=i;
while(x%i==0)x/=i;
}
}
if(x!=1)pi[++tot]=x;
for(int i=2;i<p;i++){
bool flag=true;
for(int j=1;j<=tot;j++){
if(power(i,(p-1)/pi[j],p)==1){
flag=false;
break;
}
}
if(flag){
printf("%d\n",i);
break;
}
}
}
题目描述
这是一个非常简单的问题。
wmq 如今开始学习乘法了!他为了训练自己的乘法计算能力,写出了 n n n 个整数,并且对每两个数 a , b a,b a,b 都求出了它们的乘积 a ⋅ b a\cdot b a⋅b。现在他想知道,在求出的 n ( n − 1 ) 2 \frac{n(n-1)}{2} 2n(n−1) 个乘积中,除以给定的质数 m m m 余数为 k ( 0 ≤ k < m ) k(0\leq k<m) k(0≤k<m) 的有多少个。
#include <bits/stdc++.h>
using namespace std;
typedef complex<double>E;
typedef long long ll;
const double pi=acos(-1.0);
int power(int x,int n,int p){
int ans=1;
int base=x;
while(n){
if(n&1)ans=1ll*ans*base%p;
n>>=1;
base=1ll*base*base%p;
}
return ans;
}
int n,m;
int p[40];
int tot;
int g;//原根
int to[60007];//i->g^j
int from[60007];//g^j->i
int cnt[60007];
E a[1<<18];
int R[1<<18];
ll ans[60007];
void fft(E a[],int op,int n){
for(int i=0;i<n;i++)if(i<R[i])swap(a[i],a[R[i]]);
for(int i=1;i<n;i<<=1){
E wn(cos(pi/i),op*sin(pi/i));
for(int j=0;j<n;j+=(i<<1)){
E w(1,0);
for(int k=0;k<i;k++,w*=wn){
E x=a[j+k],y=w*a[j+k+i];
a[j+k]=x+y;a[j+k+i]=x-y;
}
}
}
if(op==-1)for(int i=0;i<n;i++)a[i]/=n;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
if(m==2)g=2;
else {
tot=0;
int x=m-1;
for(int i=2;i*i<=x;i++){
if(x%i==0){
p[++tot]=i;
while(x%i==0){
x/=i;
}
}
}
if(x!=1)p[++tot]=x;
for(int i=2;i<m;i++){
bool flag=true;
for(int j=1;j<=tot;j++){
if(power(i,(m-1)/p[j],m)==1){
flag=false;
break;
}
}
if(flag){
g=i;
break;
}
}
}
int mul=1;
for(int i=0;i<m-1;i++){
to[mul]=i;
from[i]=mul;
mul=1ll*mul*g%m;
}
memset(cnt,0,sizeof(cnt));
memset(ans,0,sizeof(ans));
for(int i=1;i<=n;i++){
int x;
scanf("%d",&x);
cnt[x%m]++;
}
for(int i=1;i<m;i++){
a[to[i]]=E(cnt[i],0);
}
int len=2*m-3;
while(len!=(len&-len))len+=len&-len;
for(int i=m-1;i<len;i++)a[i]=E(0,0);
int L=31-__builtin_clz(len);
for(int i=0;i<len;i++)R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
fft(a,1,len);
for(int i=0;i<len;i++){
a[i]=a[i]*a[i];
}
fft(a,-1,len);
for(int i=0;i<2*m-3;i++){
ll tmp=(ll)(a[i].real()+0.5);
ans[from[i%(m-1)]]+=tmp;
}
for(int i=1;i<m;i++){
ans[1ll*i*i%m]-=cnt[i];
}
for(int i=1;i<m;i++){
ans[i]/=2;
}
ll sum=1ll*n*(n-1)/2;
for(int i=1;i<m;i++){
sum-=ans[i];
}
ans[0]=sum;
for(int i=0;i<m;i++){
printf("%lld\n",ans[i]);
}
}
}
Hdu 5958
题目描述
略
吐槽
卡常毒瘤!fft
p
∗
2
p
p*2p
p∗2p 就GG了!不能把两个相同的部分一次卷积。。。一定要做一次
p
∗
p
p*p
p∗p 然后使用开竖式的技巧。。。而且不能用std的complex。。。
还有就是鬼畜的行末要有空格。。。
但是题还是不错的
#include <bits/stdc++.h>
using namespace std;
const double pi=acos(-1.0);
struct E {
double r , i ;
E () {}
E ( double r , double i ) : r ( r ) , i ( i ) {}
E operator + ( const E& p ) const {
return E ( r + p.r , i + p.i ) ;
}
E operator - ( const E& p ) const {
return E ( r - p.r , i - p.i ) ;
}
E operator * ( const E& p ) const {
return E ( r * p.r - i * p.i , r * p.i + i * p.r ) ;
}
} ;
int p;
int g;//原根
double a[100007],b[100007];
int to[100007];//i->g^j
int from[100007];//g^j->i
E A[1<<20],B[1<<20];
int R[1<<20];
void fft(E a[],int op,int n){
for(int i=0;i<n;i++)if(i<R[i])swap(a[i],a[R[i]]);
for(int i=1;i<n;i<<=1){
E wn(cos(pi/i),op*sin(pi/i));
for(int j=0;j<n;j+=(i<<1)){
E w(1,0);
for(int k=0;k<i;k++,w=w*wn){
E x=a[j+k],y=w*a[j+k+i];
a[j+k]=x+y;a[j+k+i]=x-y;
}
}
}
if(op==-1)for(int i=0;i<n;i++){
a[i].r/=n;
a[i].i/=n;
}
}
int main(){
while(~scanf("%d",&p)){
if(p==103)g=5;
else g=2;
int mul=1;
for(int i=0;i<p-1;i++){
to[mul]=i;
from[i]=mul;
mul=mul*g%p;
}
for(int i=0;i<p;i++){
scanf("%lf",&a[i]);
b[i]=a[0];
if(i)b[0]+=a[i];
}
int len=2*p-3;
while(len!=(len&-len))len+=len&-len;
int L=31-__builtin_clz(len);
for(int i=0;i<len;i++)R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
for(int i=1;i<p;i++){
A[p-2-to[i]]=E(a[i],0);
}
for(int i=p-1;i<len;i++)A[i]=E(0,0);
mul=1;
for(int i=0;i<p-1;i++){
B[i]=E(pow(2,pow(sin(2*pi*mul/p),3)),0);
mul=mul*g%p;
}
for(int i=p-1;i<len;i++)B[i]=E(0,0);
fft(A,1,len);
fft(B,1,len);
for(int i=0;i<len;i++)A[i]=A[i]*B[i];
fft(A,-1,len);
for(int i=p-1;i<=2*p-4;i++)A[i].r+=A[i%(p-1)].r;
for(int i=p-2;i<=2*p-4;i++){
b[from[i-(p-2)]]+=A[i].r;
}
for(int i=0;i<p;i++)printf("%.3f ",b[i]);
printf("\n");
}
}