1001
大力猜结论
积出2*b,后面积不出来了
猜a*pi过掉了
罚时6次
大概就是
printf("%.6lf ",2*b+a*pi-5e-7);
这样的代码
我讨厌这种题.....
1002
数学题
猜结论1:gcd(2x-1,2y-1)=2gcd(x,y)-1
猜结论2:gcd(F(x),F(y))=F(gcd(x,y))
然后容斥,求出答案
#include<set> #include<map> #include<list> #include<queue> #include<stack> #include<string> #include<time.h> #include<math.h> #include<memory> #include<vector> #include<bitset> #include<fstream> #include<stdio.h> #include<utility> #include<sstream> #include<string.h> #include<iostream> #include<stdlib.h> #include<algorithm> using namespace std; int fact[20000005]; int anti_fact[20000005]; const int modo=1000000007; int power(int x,int y) { if (y==0) return 1; int t=power(x,y/2); t=(long long)t*t%modo; if (y%2==1) { t=(long long)t*x%modo; } return t; } int c(int n,int m) { return (long long)fact[n]*anti_fact[m]%modo*anti_fact[n-m]%modo; } int f[1000005]; int ans[1000005]; int main() { int i; fact[0]=1; for (i=1;i<=2000000;i++) { fact[i]=(long long)fact[i-1]*i%modo; } anti_fact[2000000]=power(fact[2000000],modo-2); for (i=2000000;i>=1;i--) { anti_fact[i-1]=(long long)anti_fact[i]*i%modo; } f[1]=1; for (i=2;i<=1000000;i++) { f[i]=f[i-1]+f[i-2]; f[i]%=(modo-1); } int zu; int t; scanf("%d",&t); for (zu=0;zu<t;zu++) { int n,k; scanf("%d%d",&k,&n); int i; for (i=1;i<=k;i++) { if (k%i==0) { ans[i]=c(n+(k/i)-1,k/i); } else { ans[i]=0; } } for (i=k;i>=1;i--) { if (ans[i]!=0) { int j; for (j=i+i;j<=k;j+=i) { ans[i]-=ans[j]; if (ans[i]<0) ans[i]+=modo; } } } int sum=0; for (i=1;i<=k;i++) { //printf("%d %d ",i,ans[i]); if (ans[i]!=0) { sum=(sum+(long long)ans[i]*(power(2,f[i])-1))%modo; } } sum=(long long)sum*power(c(n+k-1,k),modo-2)%modo; printf("%d ",sum); } return 0; }
1009
村子里面可能全是狼,它们说的话是真是假无所谓
所以不可能有铁村民
接下来考虑铁狼,如果某个人是民一定会导致矛盾那么他就是狼
如果某个人是民,他说的一定是真话,那么如果他说别人是民,那个人肯定也说了真话
这样下去
我们可以得到一个链
这个链上的所有人都是民
如果链到一个已经访问过的人,他是铁狼,那么这一些人都是铁狼
如果链变成了环(互认为民),那么这些人一定不是铁狼,因为这个环可以成立
如果链到一个可以是民的人,那么看这个民链到最后指的狼是谁
如果没指(互认民的情况),那么就不是铁狼
如果指的到人,那么看这个人是否在环内
不在的话,就全可以是民,也就是不存在铁狼
如果存在的话,这个人是铁狼,所有认这个人是民的全部是铁狼
别的依旧是民
大概就讨论这么多了................
#include<set> #include<map> #include<list> #include<queue> #include<stack> #include<string> #include<time.h> #include<math.h> #include<memory> #include<vector> #include<bitset> #include<fstream> #include<stdio.h> #include<utility> #include<sstream> #include<string.h> #include<iostream> #include<stdlib.h> #include<algorithm> using namespace std; #define next s2i39 #define tpye d923l char a[10005]; int next[1000005]; bool type[1000005]; int ans[100005]; bool vis[100005]; int main() { #ifdef absi2011 freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); #endif int t; scanf("%d",&t); int zu; for (zu=0;zu<t;zu++) { int n; scanf("%d",&n); int i; for (i=0;i<n;i++) { int x; scanf("%d%s",&x,a); next[i]=x-1; if (a[0]=='w') { type[i]=1; } else { type[i]=0; } ans[i]=-1; vis[i]=false; } int sum=0; for (i=0;i<n;i++) { if (ans[i]!=-1) { continue; } if (type[i]==1) { sum++; ans[i]=1; continue; } int now; for (now=i;;now=next[now]) { if (vis[now]) { break; } if (ans[now]==0) { break; } if (type[now]==1) { break; } vis[now]=true; } if (ans[now]==0) { int temp; for (temp=i;temp!=now;temp=next[temp]) { ans[temp]=0; } } else if (type[now]==0) { int temp; for (temp=i;ans[temp]!=1;temp=next[temp]) { ans[temp]=1; sum++; } } else if (type[now]==1) { int temp; for (temp=i;temp!=now;temp=next[temp]) { if (temp==next[now]) { break; } } if (temp==now) { //All OK for (temp=i;temp!=now;) { ans[temp]=1; sum++; int ttemp=next[temp]; type[temp]=1; next[temp]=next[now]; temp=ttemp; } } else { for (temp=next[temp];temp!=now;) { ans[temp]=1; sum++; int ttemp=next[temp]; type[temp]=1; next[temp]=next[now]; temp=ttemp; } for (temp=i;temp!=now;temp=next[temp]) { ans[temp]=0; if (temp==next[now]) { break; } } } } } printf("0 %d ",n-sum); } return 0; }
1011
又是个数学题......有点报警
讲道理别这么折磨我..让我写那么多数学题..........
首先题目里面的那个矩阵是
如果c(i,j) mod p = 0那么就是0,否则是1
那么先考虑n=1
那个矩阵的1次方,我们观察下
发现是长成这样的
1 0 .. 0
1 1 .. 0
..........
1 1 .. 1
这样的对角矩阵,那么我们k+1次方以后
我惊讶的发现,它是
C(k,k) 0 .. 0
C(k+1,k) C(k,k) .. 0
..................................
C(k+p-1,k) C(k+p-2,k) ..... C(k,k)
它们的和是
C(k+p+1,k+2)
也就是这个对角矩阵的k次方的和是
C(k+p,k+1)
那么我们考虑一下
根据Lucas定理,C(n,k) % p = C(n%p,k%p) * C(n/p,k/p) % p
那么整个矩阵就像分形一样这样分下来
所以对于pn*pn的矩阵而言,和是C(k+p,k+1)n
那么事情简单了,根据高中数学
x + x2 + x3 + .... + xn = x(xn-1)/(x-1)
所以我们只要快速求C就行了
我们枚举k,每次C根据上一次C来求
C(k+p,k+1) = (k+p)! / (k+1)! / (p-1)!
所以每次我们k增加了,求乘k+p再除以k+1就好
综上可以求出答案
#include<set> #include<map> #include<list> #include<queue> #include<stack> #include<string> #include<time.h> #include<math.h> #include<memory> #include<vector> #include<bitset> #include<fstream> #include<stdio.h> #include<utility> #include<sstream> #include<string.h> #include<iostream> #include<stdlib.h> #include<algorithm> using namespace std; const int modo=1000000007; int power(int x,int y) { if (y==0) return 1; int t=power(x,y/2); t=(long long)t*t%modo; if (y%2==1) { t=(long long)t*x%modo; } return t; } int anti_fact[200005]; bool not_prime[2000005]; int prime[200005]; int main() { int t; scanf("%d",&t); int n,cc,k; int i; int cnt=0; for (i=2;i<=2000000;i++) { if (!not_prime[i]) { prime[cnt++]=i; int j; if (i>=10000) continue; for (j=i*i;j<=2000000;j+=i) { not_prime[j]=true; } } } for (i=1;i<=200000;i++) { anti_fact[i]=power(i,modo-2); } for (i=0;i<t;i++) { scanf("%d%d%d",&cc,&n,&k); if ((n>1000000000)||(cc>100000)||(k>100000)||(cc<0)||(k<0)||(n<0)) { for(;;); } int p=prime[cc-1]; int sum=0; int j; int p1=p; int p2=(long long)(n+1)*n/2%modo; for (j=1;j<=k;j++) { p1=(long long)p1*(j+p)%modo*anti_fact[j+1]%modo; if (p1==1) { sum=(sum+(long long)p1*n%modo)%modo; } else { sum=(sum+(long long)p1*(power(p1,n)-1)%modo*power(p1-1,modo-2)%modo)%modo; } } printf("%d ",sum); } return 0; }