给定n个数a1,a2····an,依次求出相邻两个数值和,将得到一个新数列,重复上述操作,最后结果将变为一个数,问这个数除以m的余数与那些数无关?例如n=3,m=2时,第一次得到a1+a2,a2+a3,在求和得到a1+2*a2+a3,它除以2的余数和a2无关。1=<n<=10^5, 2=<m<=10^9
思路分析 :
看一下 n 的范围是 10^5 , 在二项式定理中又有这个公式
所以很容易在 O(n)的时间内推出所有项的系数,但是越往后面推 ,数会越大,爆掉 long long ,因此我们得换个方法
对 m 用唯一分解定理,那么接下来判断一个数是不是 m 的倍数,只需要判断这个数分解出的所有项的指数是否都大于等于 m 的即可
!!! 在用到容器的时候,如果有循环读入,一定要记得清空,不然一直超时
!!! 这个题最后输出的地方也好坑呀... 一直PE
代码示例 :
#define ll long long
const ll maxn = 1e6+5;
const ll mod = 1e9+7;
const double eps = 1e-9;
const double pi = acos(-1.0);
const ll inf = 0x3f3f3f3f;
vector<ll>prime;
ll e[1000], f[1000];
ll n, m;
ll k = 0;
void init(){
k = 0;
prime.clear();
memset(f, 0, sizeof(f));
memset(e, 0, sizeof(e));
for(ll i = 2; i <= sqrt(m); i++){
if (m % i == 0){
prime.push_back(i);
while(m % i == 0) {
m /= i;
e[k]++;
}
k++;
}
}
if (m != 1) {
prime.push_back(m);
e[k]++;
}
//prllf("++++ %d
", e[0]);
}
void add(ll x, ll d){
for(ll i = 0; i < prime.size(); i++){
ll su = prime[i];
while (x%su == 0){
f[i] += d;
x /= su;
}
}
}
bool check(){
for(ll i = 0; i < prime.size(); i++){
if (f[i] < e[i]) return false;
}
return true;
}
vector<ll>ans;
int main() {
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
while(cin >> n >> m){
init();
n--;
ans.clear();
for(ll i = 1; i < n; i++){
add(n-i+1, 1);
add(i, -1);
if (check()) ans.push_back(i+1);
}
printf("%d
", ans.size());
for(ll i = 0; i < ans.size(); i++){
printf("%lld%c", ans[i], i==ans.size()-1?'
':' ');
}
if (ans.size() == 0) printf("
");
}
return 0;
}