头大
这个暑假完就要去搞NOIP了。。。
暑假55天也就20次测试。。。为防万一我还是每次测试玩都写个总结。。
Day1 (65/300)
T1 切蛋糕 (55/100)
严重不服
(程序名都写对了但是最后评测系统说未找到源程序T_T)
【问题描述】
BG 有一块细长的蛋糕,长度为n。 n一些人要来BG 家里吃蛋糕, BG把蛋糕切成了若干块(整数长度),然后分给这些人。
为了公平,每个人得到的蛋糕长度和必须相等,且必须是连续的一段。
但是,BG并不知道要有多少人来。他只知道,来的人数为n的约数,且小于n。显然把蛋糕平均分成n
块一定能满足要求。但是,BG想要分出的块数尽量少。现在BG想知道,他要把蛋糕分成至少多少块,才能使得不管多少人来都能满足要求。
【输入】
输入文件名为cake.in。
输入共一个整数n,表示蛋糕的长度。
【输出】
输出文件名为cake.out。
输出共一个整数,表示分出的最少块数。
【输入输出样例1】
cake.in cake.out
6
4
【输入输出样例说明】
4 块长度分别为2、1、1、2。
【输入输出样例2】
cake.in cake.out
15
7
【输入输出样例说明】
7 块长度分别为3、2、1、3、1、2、3。
【数据说明】
对于30%的数据,2 ≤ n ≤ 15;
对于50%的数据,2 ≤ n ≤ 1,000;
对于70%的数据,2 ≤ n ≤ 1,000,000;
对于100%的数据,2 ≤ n ≤ 1,000,000,000。
源程序搞掉了。。
为什么会用到了欧拉函数????这还是信息学竞赛吗???
STD.CPP
#include<iostream>
#include<iomanip>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
long long n;
int euler(int n) //蜜汁欧拉
{
int res=n;
for(int i=2;i*i<=n;i++){
if(n%i==0){
res=res/i*(i-1);
while(n%i==0) n/=i;
}
}
if(n>1) res-=res/n;
return res;
}
int main()
{
//freopen("cake.in","r",stdin);
//freopen("cake.out","w",stdout);
cin >> n;
cout << n-euler(n) << endl;
}
T2 随机图 (0/100)
【问题描述】
BG 为了造数据,随机生成了一张n个点的无向图。他把定点标号为1~n。根据BG的随机算法,对于一个点对i,j(1<=i<j<=n),他有p‰的概率成为这张图中的一条边i-j。不同的边出现的概率是相互独立的。
为了保证数据的强度,BG要求生成的图中至少要有一个大于等于 4的连通块。于是他
想知道,在不做任何改进的情况下,根据他的算法造出强数据的概率是多少。
【输入】
输入文件名为random.in。
共一行两个整数n,p,中间用一个空格隔开,表示图的点数和边在图上的概率。
【输出】
输出文件名为random.out。
输出共一行一个实数,表示所求的概率。结果保留4 位小数。
【输入输出样例1】
random.in random.out
3 123
0.0000
【输入输出样例2】
random.in random.out
4 500
0.5938
【数据说明】
对于10%的数据,2 ≤ n ≤ 5;
对于30%的数据,2 ≤ n ≤ 7;
对于60%的数据,2 ≤ n ≤ 30;
对于100%的数据,2 ≤ n ≤ 100,0 ≤ p ≤ 1,000。
对于概率还没怎么学的我来说。。呵呵。。
就直接上题解了吧orz
STD.CPP
#include<bits/stdc++.h>
using namespace std;
typedef double db;
db C[150][150];
db f[150][150][150];
int n;
db p,powP[150];
inline int res(int i,int j,int k)
{
return i-j*2-k*3;
}
inline void pre()
{
for(int i=1;i<=100;i++)C[i][1]=i;
for(int i=2;i<=100;i++)
for(int j=2;j<=i;j++)
{
C[i][j]=C[i-1][j-1]+C[i-1][j];
}
return;
}
inline void getpow()
{
powP[0]=1;
powP[1]=((db)1-p);
for(int i=2;i<=100;i++)
{
powP[i]=powP[i-1]*powP[1];
}
}
int main()
{
pre();
scanf("%d %lf",&n,&p);
p/=1000;
getpow();
f[1][0][0]=1;
for(int i=1;i<n;i++)
for(int j=0;j<=i/2;j++)
for(int k=0;k<=i/3;k++)
{
int R=res(i,j,k);
f[i+1][j][k]+=f[i][j][k]*powP[i];
f[i+1][j+1][k]+=R*f[i][j][k]*powP[i-1]*p;
f[i+1][j-1][k+1]+=2*j*f[i][j][k]*powP[i-1]*p;
f[i+1][j][k+1]+=C[R][2]*f[i][j][k]*powP[i-2]*p*p;
f[i+1][j-1][k+1]+=j*f[i][j][k]*powP[i-2]*p*p;
}
db ans=0;
for(int j=0;j<=n/2;j++)
for(int k=0;k<=n/3;k++)
{
ans+=f[n][j][k];
}
printf("%.4f",1-ans);
}
又是dp。。。orz
T3 多项式 (10/100)
用一个大神的高精度都不行。。。要超时。。。
gg
题解玄学
【问题描述】
(才发现可以发图片。。。)
MY.CPP(前面一大段都不是我打的)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<cstring>
#include<string>
#include<cctype>
#include<iomanip>
#include<map>
#include<set>
#include<conio.h>
#include<vector>
#include<queue>
using namespace std;
struct Wint:vector<int>//用标准库vector做基类,完美解决位数问题,同时更易于实现
{
//将低精度转高精度的初始化,可以自动被编译器调用
//因此无需单独写高精度数和低精度数的运算函数,十分方便
Wint(int n=0)//默认初始化为0,但0的保存形式为空
{
push_back(n);
check();
}
Wint& check()//在各类运算中经常用到的进位小函数,不妨内置
{
while(!empty()&&!back())pop_back();//去除最高位可能存在的0
if(empty())return *this;
for(int i=1; i<size(); ++i)
{
(*this)[i]+=(*this)[i-1]/10;
(*this)[i-1]%=10;
}
while(back()>=10)
{
push_back(back()/10);
(*this)[size()-2]%=10;
}
return *this;//为使用方便,将进位后的自身返回引用
}
};
//输入输出
istream& operator>>(istream &is,Wint &n)
{
string s;
is>>s;
n.clear();
for(int i=s.size()-1; i>=0; --i)n.push_back(s[i]-'0');
return is;
}
ostream& operator<<(ostream &os,const Wint &n)
{
if(n.empty())os<<0;
for(int i=n.size()-1; i>=0; --i)os<<n[i];
return os;
}
//比较,只需要写两个,其他的直接代入即可
//常量引用当参数,避免拷贝更高效
bool operator!=(const Wint &a,const Wint &b)
{
if(a.size()!=b.size())return 1;
for(int i=a.size()-1; i>=0; --i)
if(a[i]!=b[i])return 1;
return 0;
}
bool operator==(const Wint &a,const Wint &b)
{
return !(a!=b);
}
bool operator<(const Wint &a,const Wint &b)
{
if(a.size()!=b.size())return a.size()<b.size();
for(int i=a.size()-1; i>=0; --i)
if(a[i]!=b[i])return a[i]<b[i];
return 0;
}
bool operator>(const Wint &a,const Wint &b)
{
return b<a;
}
bool operator<=(const Wint &a,const Wint &b)
{
return !(a>b);
}
bool operator>=(const Wint &a,const Wint &b)
{
return !(a<b);
}
//加法,先实现+=,这样更简洁高效
Wint& operator+=(Wint &a,const Wint &b)
{
if(a.size()<b.size())a.resize(b.size());
for(int i=0; i!=b.size(); ++i)a[i]+=b[i];
return a.check();
}
Wint operator+(Wint a,const Wint &b)
{
return a+=b;
}
//减法,返回差的绝对值,由于后面有交换,故参数不用引用
Wint& operator-=(Wint &a,Wint b)
{
if(a<b)swap(a,b);
for(int i=0; i!=b.size(); a[i]-=b[i],++i)
if(a[i]<b[i])//需要借位
{
int j=i+1;
while(!a[j])++j;
while(j>i)
{
--a[j];
a[--j]+=10;
}
}
return a.check();
}
Wint operator-(Wint a,const Wint &b)
{
return a-=b;
}
//乘法不能先实现*=,原因自己想
Wint operator*(const Wint &a,const Wint &b)
{
Wint n;
n.assign(a.size()+b.size()-1,0);
for(int i=0; i!=a.size(); ++i)
for(int j=0; j!=b.size(); ++j)
n[i+j]+=a[i]*b[j];
return n.check();
}
Wint& operator*=(Wint &a,const Wint &b)
{
return a=a*b;
}
//除法和取模先实现一个带余除法函数
Wint divmod(Wint &a,const Wint &b)
{
Wint ans;
for(int t=a.size()-b.size(); a>=b; --t)
{
Wint d;
d.assign(t+1,0);
d.back()=1;
Wint c=b*d;
while(a>=c)
{
a-=c;
ans+=d;
}
}
return ans;
}
Wint operator/(Wint a,const Wint &b)
{
return divmod(a,b);
}
Wint& operator/=(Wint &a,const Wint &b)
{
return a=a/b;
}
Wint& operator%=(Wint &a,const Wint &b)
{
divmod(a,b);
return a;
}
Wint operator%(Wint a,const Wint &b)
{
return a%=b;
}
Wint pow(const Wint &n,const Wint &k)
{
if(k.empty())return 1;
if(k==2)return n*n;
if(k.back()%2)return n*pow(n,k-1);
return pow(pow(n,k/2),2);
}
//顺手实现一个快速幂,可以看到和普通快速幂几乎无异
Wint powx(const Wint &n,const Wint &k,const Wint &d)
{
if(k.empty())return 1;
if(k==2)return n*n%d;
if(k.back()%2)return n*pow(n,k-1)%d;
return pow(pow(n,k/2),2)%d;
}
分割线//
/*
//通过重载运算符,还可以实现++、--、^、!、逻辑运算符等很多运算,十分简单,此处都不写了
int main()//现在你完全可以像int一般便捷地使用Wint,如下
{
Wint a,b;
//可以把b改成int型,仍能正常使用
cin>>a>>b;//其他运算可以直接调用了
cout<<(a<b)<<endl
<<(a==b)<<endl
<<a+b<<endl
<<a-b<<endl
<<a*b<<endl
<<a/b<<endl
<<a%b<<endl
<<pow(a,b);
return 0;
}*/
int main()
{
//freopen("polynomial.in","r",stdin);
//freopen("polynomial.out","w",stdout);
int n;
Wint k,l,m,t,ans,jud=0;
Wint a0=0,a1=0,a2=0,a3=0,a4=0,a5=0,a6=0,a7=0,a8=0,a9=0,a10=0;
cin >> n >> k >> l >> m;
//cout << n << " " << k << " " << l << " " << m << endl;
if(n==0) cin >> a0 ;
if(n==1) cin >> a1 >> a0 ;
if(n==2) cin >> a2 >> a1 >> a0 ;
if(n==3) cin >> a3 >> a2 >> a1 >> a0 ;
if(n==4) cin >> a4 >> a3 >> a2 >> a1 >> a0 ;
if(n==5) cin >> a5 >> a4 >> a3 >> a2 >> a1 >> a0 ;
if(n==6) cin >> a6 >> a5 >> a4 >> a3 >> a2 >> a1 >> a0 ;
if(n==7) cin >> a7 >> a6 >> a5 >> a4 >> a3 >> a2 >> a1 >> a0 ;
if(n==8) cin >> a8 >> a7 >> a6 >> a5 >> a4 >> a3 >> a2 >> a1 >> a0 ;
if(n==9) cin >> a9 >> a8 >> a7 >> a6 >> a5 >> a4 >> a3 >> a2 >> a1 >> a0 ;
if(n==10) cin >> a10 >> a9 >> a8 >> a7 >> a6 >> a5 >> a4 >> a3 >> a2 >> a1 >> a0 ;
//cout << a0 << " " << a1 << " " << a2 << " " << a3 << " " << a4 << " " << a5 << " " << a6 << " " << a7 << " " << a8 << " " << a9 << " " << a10 << " " << endl;
Wint hi = pow(10,m);
for(t=k;t<=k+l-1;)
{
//cout << "Case " << t-k+1 << ": " << endl;
if(a0>jud)
{
ans += (a0)*(powx(t,0,hi));
ans %= pow(10,m); //cout << "Σa0 = " << ans << endl;
}
if(a1>jud)
{
ans += (a1)*(powx(t,1,hi));
ans %= pow(10,m); //cout << "Σa1 = " << ans << endl;
}
if(a2>jud)
{
ans += (a2)*(powx(t,2,hi));
ans %= pow(10,m); //cout << "Σa2 = " << ans << endl;
}
if(a3>jud)
{
ans += (a3)*(powx(t,3,hi));
ans %= pow(10,m); //cout << "Σa3 = " << ans << endl;
}
if(a4>jud)
{
ans += (a4)*(powx(t,4,hi));
ans %= pow(10,m); //cout << "Σa4 = " << ans << endl;
}
if(a5>jud)
{
ans += (a5)*(powx(t,5,hi));
ans %= pow(10,m); //cout << "Σa5 = " << ans << endl;
}
if(a6>jud)
{
ans += (a6)*(powx(t,6,hi));
ans %= pow(10,m); //cout << "Σa5 = " << ans << endl;
}
if(a6>jud)
{
ans += (a6)*(powx(t,6,hi));
ans %= pow(10,m); //cout << "Σa5 = " << ans << endl;
}
if(a7>jud)
{
ans += (a7)*(powx(t,7,hi));
ans %= pow(10,m); //cout << "Σa5 = " << ans << endl;
}
if(a8>jud)
{
ans += (a8)*(powx(t,8,hi));
ans %= pow(10,m); //cout << "Σa5 = " << ans << endl;
}
if(a9>jud)
{
ans += (a9)*(powx(t,9,hi));
ans %= pow(10,m); //cout << "Σa5 = " << ans << endl;
}if(a10>jud)
{
ans += (a10)*(powx(t,10,hi));
ans %= pow(10,m); //cout << "Σa5 = " << ans << endl;
}
cout << ans << endl;
ans = 0;
t = t+1;
}
return 0;
}
卵用,只能过一个点
STD.CPP(玄学)
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define K 100000000
#define LEN 8
#define ll long long
using namespace std;
int N,L,M;
struct num
{
int a[605];
num() {memset(a,0,sizeof(a)),a[0]=1;}
num(const char*s)
{
memset(a,0,sizeof(a));
int l=strlen(s);
a[0]=min(M/LEN+10,(l-1)/LEN+1);
for (int p=1; l>0; p++)
{
int x=0;
for (int i=max(0,l-LEN); i<l; i++) (x*=10)+=s[i]-48;
l-=LEN,a[p]=x;
}
}
void operator ++(int)
{
a[1]++;
for (int i=1; a[i]>=K; i++) a[i]-=K,a[i+1]++;
if (a[a[0]+1]) a[0]++;
a[0]=min(a[0],M/LEN+10);
}
friend num operator +(const num&A,const num&B)
{
num C;
C[0]=max(A[0],B[0]);
for (int i=1; i<=C[0]; i++)
{
C[i]+=A[i]+B[i];
if (C[i]>=K) C[i]-=K,C[i+1]++;
}
if (C[C[0]+1]) C[0]++;
C[0]=min(C[0],M/LEN+10);
return C;
}
friend num operator -(const num&A,const num&B)
{
num C;
C[0]=A[0];
for (int i=1; i<=C[0]; i++)
{
C[i]+=A[i]-B[i];
if (C[i]<0) C[i]+=K,C[i+1]--;
}
for (;C[0]>1&&!C[C[0]]; C[0]--);
return C;
}
friend num operator *(const num&A,const num&B)
{
num C;
C[0]=min(M/LEN+10,A[0]+B[0]);
for (int i=1; i<=A[0]; i++)
for (int j=1; j<=B[0]; j++)
{
ll x=1ll*A[i]*B[j]+C[i+j-1];
C[i+j]+=x/K,C[i+j-1]=x%K;
}
for (;C[0]>1&&!C[C[0]]; C[0]--);
return C;
}
int&operator [](int x) {return a[x];}
const int&operator [](int x) const {return a[x];}
void print() const
{
if (a[0]<=M/LEN)
{
printf("%d",a[a[0]]);
for (int i=a[0]-1; i; i--) printf("%0*d",LEN,a[i]);
puts("");
}
else
{
int l=M%LEN,r=M/LEN,b[15],t=0;
for (int i=1,j=a[r+1]; j&&i<=l; i++,j/=10) b[++t]=j%10;
for (;t&&!b[t]; t--);
for (int i=t; i; i--) printf("%d",b[i]);
if (!t)
{
for (;r>1&&!a[r]; r--);
printf("%d",a[r]),r--;
}
for (int i=r; i; i--) printf("%0*d",LEN,a[i]);
puts("");
}
}
} a[12],f[12][1002],S;
void init()
{
char s[2005];
scanf("%d%s%d%d",&N,s,&L,&M),S=s;
for (int i=N; i>=0; i--) scanf("%s",s),a[i]=s;
}
void doit()
{
for (int i=1; i<=N+1; i++,S++)
for (int j=N; j>=0; j--) f[N][i]=f[N][i]*S+a[j];
for (int i=N-1; i>=0; i--)
for (int j=1; j<=i+1; j++) f[i][j]=f[i+1][j+1]-f[i+1][j];
for (int i=2; i<=L; i++) f[0][i]=f[0][1];
for (int k=N+2; k<=L; k++)
for (int i=1; i<=N; i++) f[i][k-N+i]=f[i][k-N+i-1]+f[i-1][k-N+i-1];
for (int i=1; i<=L; i++) f[N][i].print();
}
int main()
{
//freopen("polynomial.in","r",stdin);
//freopen("polynomial.out","w",stdout);
init();
doit();
return 0;
}
话说题解都有两个点超时