bzoj3434 wc2014 穿梭时空(1)

传送门:http://uoj.ac/problem/54
为啥养成了看题解,写不对又看标程的习惯了呢?一定要改啊!!!!!增强代码能力好不好?
跑题了,,,
越来越喜欢鬼畜的题了啊,,,
这是道很有意思的数论题,,,idea非常好啊,我的思路是枚举最左下角的两个点然后判断是否剩余的点有c-2个,直接有问题所以去看了题解,结果各种看不懂就写了一个60分暴力,,贴两个题解先学习着,,,,%%%:1.Popoqqq的:http://blog.csdn.net/PoPoQQQ/article/details/42705835
2.课件:http://wenku.baidu.com/link?url=FeXsCSB1jyFbGc5_r4wlIfr8s_QBlOheyadL5PPdt9Z5-844bYXvTvW39M9Oy8pIKFokOTH5q572wxob2OgypU6_bOEMJsfnL_zj7AB8DZ3
教训:1.该用longlong还是要用longlong,一开始用int强转出错了
2.注意写程序要专心不能走神啊,,看着纸上的式子打还打错了,,我还是退役保平安吧,,,
思路:1.枚举方式很多种多样啊,,枚举起点和终点,我们枚举的对象总是有效的可以算下去的,还要满足枚举对象要最小化,比如本题要枚举的是差值(很重要的思想)
2.两个点之间的整点个数gcd(x2-x1,y2-y1)-1(很好证不多说)
3.由二维推广到n维的思想特别重要
4.反演要有序进行,化到最简形式
60分:

#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#define maxn 20
#define N 100000
#define p 10007
using namespace std;
bool not_prime[N+5],flag;
int n,c1,m[maxn],mini;
long long tot,prime[N+5],mu[N+5],c[N+5][maxn+5],f[N+5],s,ans;
void shai(){
    tot=0;
    memset(not_prime,0,sizeof(not_prime));
    mu[1]=1; 
    for (int i=2;i<=N;++i){
        if (!not_prime[i]) { prime[++tot]=i; mu[i]=-1;}
        for (int j=1;j<=tot;++j)
          if (prime[j]*i>N) break;
          else {  not_prime[prime[j]*i]=1;
              if (!(i%prime[j])) { mu[i*prime[j]]=0; break;}
              else mu[i*prime[j]]=-mu[i];
          }
    }
}

void make_it(){
    for (int i=0;i<=N;++i) c[i][0]=1;
    for (int i=1;i<=N;++i)
      for (int j=1;j<=maxn&&j<=i;++j)
        c[i][j]=(c[i-1][j]+c[i-1][j-1])%p;
}

void init(){
    flag=0;
    s=1;
    mini=0x7fffffff;
    scanf("%d%d",&n,&c1);
    for (int i=1;i<=n;++i) scanf("%d",&m[i]);
    for (int i=1;i<=n;++i) mini=min(mini,m[i]);
    memset(f,0,sizeof(f));
    if (n==1) flag=1;
}

void DO_IT(){
    if (!flag){
    for (int i=1;i<=mini;++i)
      for (int j=i;j<=mini;j+=i)
        f[j]=(f[j]+c[i-1][c1-2]*mu[j/i]%p+p)%p;
    ans=0;
    for (int i=1;i<=mini;++i){
      long long sum=1;
      for (int j=1;j<=n;++j){
        long long t=m[j]/i;
        long long t1=((t*m[j]-(t+1)*t*i/2)%p+p)%p;
        sum=sum*t1%p; }
      sum=sum*f[i]%p;
      ans=(ans+sum)%p; }}
      else ans=c[m[1]][c1];
}

int main(){
    int T;
    scanf("%d",&T);
    shai();
    make_it();
    while (T--){
      init();
      DO_IT();
      cout<<ans<<endl;}
      //printf("%64d\n",ans);}
    return 0;
}

你可能感兴趣的:(bzoj3434 wc2014 穿梭时空(1))