2016.1.27
试题描述
|
杨辉三角是形如如下的数字三角形: 1 1 1 1 2 1 …… 现在想求出杨辉三角第N行的N个数中,有多少个数能被给定的质数p整除。 |
输入
|
一行两个空格隔开的整数N和p
|
输出
|
输出一个整数,表示第N行能被给定的质数p整除的个数
|
输入示例
|
3 2
|
输出示例
|
1
|
其他说明
|
对于60%的数据,N≤30,p≤1000,对于80%的数据,N≤1000,p≤1000,对于100%的数据,N≤〖10〗^9,p≤1000
|
然后就一个一个试呗
#include<iostream> using namespace std; int a[1005],e,ans; int main() { int n,p,b,ct; scanf("%d%d",&n,&p); b=n-=1; while(b) { a[++e]=b%p; b/=p; } for(int i=0;i<=n;i++) { b=i;ct=1; while(b) { if(b%p>a[ct]) {ans+=1;break;} else {ct++;b/=p;} } } printf("%d",ans); }
然后果断TLE
然后根据杨辉三角的对称性,砍一半
#include<iostream> using namespace std; int a[1005],e,ans; int main() { int n,p,b,ct; scanf("%d%d",&n,&p); b=n-=1; while(b) { a[++e]=b%p; b/=p; } for(int i=0;i<(n+1)/2;i++) { b=i;ct=1; while(b) { if(b%p>a[ct]) {ans+=1;break;} else {ct++;b/=p;} } } ans*=2; if(n+1&1) { b=n/2;ct=1; while(b) { if(b%p>a[ct]) {ans+=1;break;} else {ct++;b/=p;} } } printf("%d",ans); }
然并卵,依旧TLE
于是机智的我想到了构造
还想到了状态压缩
就是二进制某一位为1表示构造的数在p进制下该位上比n在对应位上大
#include<iostream> using namespace std; int a[105],e,ans; int main() { int n,p,b,ct; scanf("%d%d",&n,&p); b=n-=1; while(b) { a[++e]=b%p; b/=p; } for(int t = e-1 ; t >= 1 ; t-- ) { for(int i = ( 1 << t ) - 1 ; i >= 1 ; i-- ) { b=i;ct=a[t+1]; for(int j = t-1 ; j >= 0; j-- ) { if(1<<j&b) ct*=p-1-a[j+1]; else ct*=a[j+1]+1; } ans+=ct; } } printf("%d",ans); }
AC后激动的我瞬间觉得我有做神犇的潜质
但我发现其他人的代码都特短。。。
我方了
冷静后,发现我傻*了
明明可以反着算。。。要知道根据卢卡斯定理构造模p不等于0的数有多简单。。。
看了代码瞬间就懂的
AC代码:
#include<iostream> using namespace std; int e,ans=1; int main() { int n,p,b; scanf("%d%d",&n,&p); b=n-1; while(b) { ans*=b%p+1; b/=p; } printf("%d",n-ans); }