题解—Math
考场上理论爆零了,可见我有多菜。
这就是一个定理的板子,过了大样例就没有思考,太可恶了。
可见我的数学方面尤其薄弱
定理\(ax+by=c\)有整数解,当且仅当\(gcd(x,y)|c\)
大佬们都说显然,就我一个菜鸡看不出来还得证明。
\(\ \ \ \ \ \ \ ax+by=c\)
设 \(\ \ gcd(x,y)=g\)
则 \(\ \ x=tg,y=zg\)
则 \(\ \ ax+by=atg+bzg=(at+bz)g=c\)
得证
扩展到多元,有解当且进当所有数的\(gcd\)整除\(k\)
也就是说,答案是一个等差数列,公差是\(Gcd_{i=1}^{n}(a[i])\)
我们可以让他不断乘上一个数之后取模,直到出现循环节为止。
但其实这个循环节并不需要暴力去找。
容易发现,因为我们每次加\(gcd\),所以肯定是关于\(gcd\)的因子的等差数列。
有由于我们取模\(k\),所以肯定是关于\(k\)的因子的等差数列。
所以整个数列的公差就是\(gcd(Gcd,k)\)
code
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <assert.h>
#define R register int
#define int long long
#define printf Ruusupuu = printf
#define scanf Ruusupuu = scanf
int Ruusupuu ;
using namespace std ;
typedef long long L ;
typedef long double D ;
typedef pair< int , int > PI ;
const int N = 2e6 + 10 ;
inline int read(){
int w = 0 ; bool fg = 0 ; char ch = getchar() ;
while( ch > '9' || ch < '0' ) fg |= ( ch == '-' ) , ch = getchar() ;
while( ch <= '9' && ch >= '0' ) w = ( w << 1 ) + ( w << 3 ) + ( ch - '0' ) , ch = getchar() ;
return fg ? -w : w ;
}
int n , k , a [N] , cd ;
bool fg [N] ;
int gcd( int x , int y ){
return ( y == 0 ) ? x : gcd( y , x % y ) ;
}
void sc(){
n = read() , k = read() ;
for( R i = 1 ; i <= n ; i ++ ) a [i] = read() ;
}
void work(){
cd = k ;
for( R i = 1 ; i <= n ; i ++ )
cd = gcd( a [i] , cd ) ;
int ans = 0 ;
for( R i = 0 ; i < k ; i ++ ) if( i % cd == 0 ) ans ++ ;
printf( "%lld\n" , ans ) ;
for( R i = 0 ; i < k ; i ++ ) if( i % cd == 0 ) printf( "%lld " , i ) ;
}
signed main(){
sc() ;
work() ;
return 0 ;
}
还有一个小事情,就是考场上因为\(diff\)操作花了很多时间,导致后面时间分配有点不合理。
本质是\(diff\)太垃圾,各种操作他都判断不一样。
所以我们用\(diff-Z\),忽略各种空白。
$The \ light \ has \ betrayed \ me$

浙公网安备 33010602011771号