wmq的A×B Problem

wmq的A×B Problem

题目链接:http://oj.xjtuacm.com/problem/13/

题目大意:$T$组数据,每组给出$n$个数$a_i$及一个素数$m$,求这$n$个数两两相乘模$m$余$k$有多少个($0\leqslant k < m$).

数论+FFT

原根的概念

设$n \geqslant 1$,$(a,n)=1$,使得$a^d \equiv 1(mod n)$成立的最小的正整数$d$,被称为$a$对模$n$的阶,记做$\delta_n(a)$.

当$\delta_n(a)=\varphi(n)$时,称$a$为模$n$的一个原根.

待更...

代码如下:

  1 #include <cstdio>
  2 #include <cmath>
  3 #include <iostream>
  4 #include <cstring>
  5 #define N 60010
  6 using namespace std;
  7 typedef long long ll;
  8 ll T,n,m,t,r,len,phi;
  9 ll ans[N],mod[N],rt[N],temp[4*N];
 10 const double pi=acos(-1.0);
 11 struct Complex{
 12     double r,i;
 13     Complex(double r=0,double i=0):r(r),i(i){};
 14     Complex operator+(const Complex &rhs){return Complex(r+rhs.r,i+rhs.i);}
 15     Complex operator-(const Complex &rhs){return Complex(r-rhs.r,i-rhs.i);}
 16     Complex operator*(const Complex &rhs){return Complex(r*rhs.r-i*rhs.i,i*rhs.r+r*rhs.i);}
 17 }a[4*N],b[4*N],c[4*N];
 18 void sincos(double theta,double &p0,double &p1){
 19     p0=sin(theta);p1=cos(theta);
 20 }
 21 void fft_main(Complex P[], ll n, ll oper){
 22     for(ll i=1,j=0;i<n-1;i++){
 23         for(ll s=n;j^=s>>=1,~j&s;);
 24         if(i<j)swap(P[i],P[j]);
 25     }
 26     Complex unit_p0;
 27     for(ll d=0;(1<<d)<n;d++){
 28         ll m=1<<d,m2=m*2;
 29         double p0=pi/m*oper;
 30         sincos(p0,unit_p0.i,unit_p0.r);
 31         for(ll i=0;i<n;i+=m2){
 32             Complex unit=1;
 33             for(ll j=0;j<m;j++){
 34                 Complex &P1=P[i+j+m],&P2=P[i+j];
 35                 Complex t=unit*P1;
 36                 P1=P2-t; P2=P2+t;
 37                 unit=unit*unit_p0;
 38             }
 39         }
 40     }if(oper==-1)for(ll i=0;i<len;i++)P[i].r/=len;
 41 }
 42 void fft(Complex a[],Complex b[],ll len){
 43     fft_main(a,len,1);fft_main(b,len,1);
 44     for(ll i=0;i<len;++i)c[i]=a[i]*b[i];
 45     fft_main(c,len,-1);
 46 }
 47 void fft_init(){
 48     len=1;
 49     while(len<2*phi)len<<=1;
 50     ll i=0;
 51     for(ll x=1;i<phi;++i){
 52         rt[i]=mod[x];
 53         a[i].r=b[i].r=rt[i];
 54         a[i].i=b[i].i=0;
 55         x=(x*r)%m;
 56     }
 57     for(;i<len;++i){
 58         a[i].r=b[i].r=0;
 59         a[i].i=b[i].i=0;
 60     }
 61 }
 62 ll powmod(ll a,ll n,ll m){
 63     ll r=1,t=a;
 64     while(n){
 65         if(n&1)r=(r*t)%m;
 66         t=(t*t)%m;
 67         n>>=1;
 68     }
 69     return r;
 70 }
 71 ll Root(ll m){
 72     for(ll i=2,j;i<m;++i){
 73         for(j=2;j<phi;++j)
 74             if(powmod(i,j,m)==1)
 75                 break;
 76         if(j==phi)return i;
 77     }
 78     return 0;
 79 }
 80 ll in(){
 81     ll res=0,flag=0,ch;
 82     if((ch=getchar())==‘-‘)flag=1;
 83     else if(‘0‘<=ch&&ch<=‘9‘)res=ch-‘0‘;
 84     while(‘0‘<=(ch=getchar())&&ch<=‘9‘)res=res*10+ch-‘0‘;
 85     return flag?-res:res;
 86 }
 87 void out(ll x){
 88     if(x>9)out(x/10);
 89     putchar(x%10+‘0‘);
 90 }
 91 void solve(){
 92     for(ll i=0;i<len;++i){
 93         temp[i]=c[i].r+0.5;
 94         temp[i]/=2;
 95     }
 96     for(ll i=0;i<phi;++i){
 97         temp[2*i]-=rt[i]*rt[i]/2;
 98         temp[2*i]+=rt[i]*(rt[i]-1)/2;
 99     }
100     for(ll i=0,x=1;i<len;++i){
101         ans[x]+=temp[i];
102         x=(x*r)%m;
103     }
104     ans[0]=mod[0]*(n-mod[0])+mod[0]*(mod[0]-1)/2;
105 }
106 void init(){
107     memset(temp,0,sizeof(temp));
108     n=in();m=in();
109     for(ll i=0;i<m;++i)mod[i]=0;
110     for(ll i=0;i<m;++i)ans[i]=0;
111     for(ll i=0;i<n;++i){
112         t=in();
113         mod[t%m]++;
114     }
115 }
116 int main(void){
117     T=in();
118     while(T--){
119         init();
120         phi=m-1;
121         r=Root(m);
122         fft_init();
123         fft(a,b,len);
124         solve();
125         for(ll i=0;i<m;++i){
126             out(ans[i]);
127             puts("");
128         }
129     }
130 }
时间: 2024-08-25 09:11:30

wmq的A×B Problem的相关文章

XJTUOJ wmq的A&#215;B Problem FFT

wmq的A×B Problem 发布时间: 2017年4月9日 17:06   最后更新: 2017年4月9日 17:07   时间限制: 3000ms   内存限制: 512M 描述 这是一个非常简单的问题. wmq如今开始学习乘法了!他为了训练自己的乘法计算能力,写出了n个整数,并且对每两个数a,b都求出了它们的乘积a×b.现在他想知道,在求出的n(n−1)2个乘积中,除以给定的质数m余数为k(0≤k<m)的有多少个. 输入 第一行为测试数据的组数. 对于每组测试数据,第一行为2个正整数n,

南阳524 A-B Problem

A-B Problem 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 A+B问题早已经被大家所熟知了,是不是很无聊呢?现在大家来做一下A-B吧. 现在有两个实数A和B,聪明的你,能不能判断出A-B的值是否等于0呢? 输入 有多组测试数据.每组数据包括两行,分别代表A和B. 它们的位数小于100,且每个数字前中可能包含+,- 号. 每个数字前面和后面都可能有多余的0. 每组测试数据后有一空行. 输出 对于每组数据,输出一行. 如果A-B=0,输出YES,否则输出NO

NYOJ A-B Problem

A-B Problem 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 A+B问题早已经被大家所熟知了,是不是很无聊呢?现在大家来做一下A-B吧. 现在有两个实数A和B,聪明的你,能不能判断出A-B的值是否等于0呢? 输入 有多组测试数据.每组数据包括两行,分别代表A和B. 它们的位数小于100,且每个数字前中可能包含+,- 号. 每个数字前面和后面都可能有多余的0. 每组测试数据后有一空行. 输出 对于每组数据,输出一行. 如果A-B=0,输出YES,否则输出NO

NYOJ:题目524 A-B Problem

题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=860 My思路: 先用两个字符串储存这两个实数,然后再用另外两个字符串储存去掉符号和前后多余的0后的新"实数",最后只需要比较两个化简后的新字符就ok了. My代码实现: 1 #include<iostream> 2 using namespace std; 3 string simplify(string s) { //去字符串s的正负号和首尾多余的0 4 str

P2421 A-B数对(增强版)

题目背景 woshiren在洛谷刷题,感觉第一题:求两数的和(A+B Problem)太无聊了,于是增加了一题:A-B Problem,难倒了一群小朋友,哈哈. 题目描述 给出N 个从小到大排好序的整数,一个差值C,要求在这N个整数中找两个数A 和B,使得A-B=C,问这样的方案有多少种? 例如:N=5,C=2,5 个整数是:2 2 4 8 10.答案是3.具体方案:第3 个数减第1 个数:第3 个数减第2 个数:第5 个数减第4 个数. 输入输出格式 输入格式: 第一行2 个正整数:N,C.

洛谷——P2421 A-B数对(增强版)

题目背景 woshiren在洛谷刷题,感觉第一题:求两数的和(A+B Problem)太无聊了,于是增加了一题:A-B Problem,难倒了一群小朋友,哈哈. 题目描述 给出N 个从小到大排好序的整数,一个差值C,要求在这N个整数中找两个数A 和B,使得A-B=C,问这样的方案有多少种? 例如:N=5,C=2,5 个整数是:2 2 4 8 10.答案是3.具体方案:第3 个数减第1 个数:第3 个数减第2 个数:第5 个数减第4 个数. 输入输出格式 输入格式: 第一行2 个正整数:N,C.

【南阳OJ分类之大数问题】题目+AC代码汇总

声明:题目部分皆为南阳OJ题目,代码部分包含AC代码(可能不止一个)和标程. 由于大数问题用c/c++写比较麻烦,而Java的大数类又很好用,所以基本为java代码.实际上竞赛很少会考大数问题,因为竞赛是比的算法,而不是语言特性,不过很多都是大数据,数据上千万级别的,所以算法又很关键,显然那和这篇博客也没啥关系. 题目不是太难,大家和本人就权当学习或复习下Java吧O(∩_∩)O~. 该分类南阳oj地址:http://acm.nyist.edu.cn/JudgeOnline/problemset

【题解】差

题目描述 楠楠在网上刷题,感觉第一题:求两数的和(A+B Problem)太无聊了,于是增加了一题:A-B Problem,难倒了一群小朋友,哈哈. 题目是这样的:给出N个从小到大排好序的整数,一个差值C,要求在这N个整数中找两个数A和B,使得A-B=C,问这样的方案有多少种? 例如:N=5,C=2,5个整数是:2 2 4 8 10.答案是3. 具体方案:第3个数减第1个数:第3个数减第2个数:第5个数减第4个数. 输入输出格式 输入格式 第一行,两个正整数:N,C. 第二行,N个整数:已经有序

diverta 2019 Programming Contest

AB 签到(A是a-b problem就不放code了) #include<bits/stdc++.h> using namespace std; int r,g,b,n,ans; int main() { cin>>r>>g>>b>>n; for(int i=0;i*r<=n;i++) for(int j=0;i*r+j*g<=n;j++) if((n-i*r-j*g)%b==0)ans++; cout<<ans<